/**
*Submitted for verification at polygonscan.com on 2022-11-10
*/
// File: @onchain-id/solidity/contracts/interface/IERC734Legacy.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
/**
* @dev interface of the ERC734 (Key Holder) standard as defined in the EIP.
*/
interface IERC734Legacy {
/**
* @dev Emitted when an execution request was approved.
*
* Specification: MUST be triggered when approve was successfully called.
*/
event Approved(uint256 indexed executionId, bool approved);
/**
* @dev Emitted when an execute operation was approved and successfully performed.
*
* Specification: MUST be triggered when approve was called and the execution was successfully approved.
*/
event Executed(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data);
/**
* @dev Emitted when an execution request was performed via `execute`.
*
* Specification: MUST be triggered when execute was successfully called.
*/
event ExecutionRequested(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data);
event ExecutionFailed(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data);
/**
* @dev Emitted when a key was added to the Identity.
*
* Specification: MUST be triggered when addKey was successfully called.
*/
event KeyAdded(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType);
/**
* @dev Emitted when a key was removed from the Identity.
*
* Specification: MUST be triggered when removeKey was successfully called.
*/
event KeyRemoved(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType);
/**
* @dev Emitted when the list of required keys to perform an action was updated.
*
* Specification: MUST be triggered when changeKeysRequired was successfully called.
*/
event KeysRequiredChanged(uint256 purpose, uint256 number);
/**
* @dev Adds a _key to the identity. The _purpose specifies the purpose of the key.
*
* Triggers Event: `KeyAdded`
*
* Specification: MUST only be done by keys of purpose 1, or the identity itself. If it's the identity itself, the approval process will determine its approval.
*/
function addKey(bytes32 _key, uint256 _purpose, uint256 _keyType) external returns (bool success);
/**
* @dev Approves an execution or claim addition.
*
* Triggers Event: `Approved`, `Executed`
*
* Specification:
* This SHOULD require n of m approvals of keys purpose 1, if the _to of the execution is the identity contract itself, to successfully approve an execution.
* And COULD require n of m approvals of keys purpose 2, if the _to of the execution is another contract, to successfully approve an execution.
*/
function approve(uint256 _id, bool _approve) external returns (bool success);
/**
* @dev Passes an execution instruction to an ERC725 identity.
*
* Triggers Event: `ExecutionRequested`, `Executed`
*
* Specification:
* SHOULD require approve to be called with one or more keys of purpose 1 or 2 to approve this execution.
* Execute COULD be used as the only accessor for `addKey` and `removeKey`.
*/
function execute(address _to, uint256 _value, bytes calldata _data) external payable returns (uint256 executionId);
/**
* @dev Returns the full key data, if present in the identity.
*/
function getKey(bytes32 _key) external view returns (uint256[] memory purposes, uint256 keyType, bytes32 key);
/**
* @dev Returns the list of purposes associated with a key.
*/
function getKeyPurposes(bytes32 _key) external view returns(uint256[] memory _purposes);
/**
* @dev Returns an array of public key bytes32 held by this identity.
*/
function getKeysByPurpose(uint256 _purpose) external view returns (bytes32[] memory keys);
/**
* @dev Returns TRUE if a key is present and has the given purpose. If the key is not present it returns FALSE.
*/
function keyHasPurpose(bytes32 _key, uint256 _purpose) external view returns (bool exists);
/**
* @dev Removes _purpose for _key from the identity.
*
* Triggers Event: `KeyRemoved`
*
* Specification: MUST only be done by keys of purpose 1, or the identity itself. If it's the identity itself, the approval process will determine its approval.
*/
function removeKey(bytes32 _key, uint256 _purpose) external returns (bool success);
}
// File: @onchain-id/solidity/contracts/interface/IERC735Legacy.sol
/**
* @dev interface of the ERC735 (Claim Holder) standard as defined in the EIP.
*/
interface IERC735Legacy {
/**
* @dev Emitted when a claim request was performed.
*
* Specification: Is not clear
*/
event ClaimRequested(uint256 indexed claimRequestId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri);
/**
* @dev Emitted when a claim was added.
*
* Specification: MUST be triggered when a claim was successfully added.
*/
event ClaimAdded(bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri);
/**
* @dev Emitted when a claim was removed.
*
* Specification: MUST be triggered when removeClaim was successfully called.
*/
event ClaimRemoved(bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri);
/**
* @dev Emitted when a claim was changed.
*
* Specification: MUST be triggered when changeClaim was successfully called.
*/
event ClaimChanged(bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri);
/**
* @dev Get a claim by its ID.
*
* Claim IDs are generated using `keccak256(abi.encode(address issuer_address, uint256 topic))`.
*/
function getClaim(bytes32 _claimId) external view returns(uint256 topic, uint256 scheme, address issuer, bytes memory signature, bytes memory data, string memory uri);
/**
* @dev Returns an array of claim IDs by topic.
*/
function getClaimIdsByTopic(uint256 _topic) external view returns(bytes32[] memory claimIds);
/**
* @dev Add or update a claim.
*
* Triggers Event: `ClaimRequested`, `ClaimAdded`, `ClaimChanged`
*
* Specification: Requests the ADDITION or the CHANGE of a claim from an issuer.
* Claims can requested to be added by anybody, including the claim holder itself (self issued).
*
* _signature is a signed message of the following structure: `keccak256(abi.encode(address identityHolder_address, uint256 topic, bytes data))`.
* Claim IDs are generated using `keccak256(abi.encode(address issuer_address + uint256 topic))`.
*
* This COULD implement an approval process for pending claims, or add them right away.
* MUST return a claimRequestId (use claim ID) that COULD be sent to the approve function.
*/
function addClaim(uint256 _topic, uint256 _scheme, address issuer, bytes calldata _signature, bytes calldata _data, string calldata _uri) external returns (bytes32 claimRequestId);
/**
* @dev Removes a claim.
*
* Triggers Event: `ClaimRemoved`
*
* Claim IDs are generated using `keccak256(abi.encode(address issuer_address, uint256 topic))`.
*/
function removeClaim(bytes32 _claimId) external returns (bool success);
}
// File: @onchain-id/solidity/contracts/interface/LegacyIIdentity.sol
interface LegacyIIdentity is IERC734Legacy, IERC735Legacy {}
// File: @onchain-id/solidity/contracts/interface/IClaimIssuerLegacy.sol
interface IClaimIssuerLegacy is LegacyIIdentity {
function revokeClaim(bytes32 _claimId, address _identity) external returns(bool);
function getRecoveredAddress(bytes calldata sig, bytes32 dataHash) external pure returns (address);
function isClaimRevoked(bytes calldata _sig) external view returns (bool);
function isClaimValid(LegacyIIdentity _identity, uint256 claimTopic, bytes calldata sig, bytes calldata data)
external
view returns (bool);
}
// File: contracts/registry/ITrustedIssuersRegistryLegacy.sol
/**
* NOTICE
*
* The T-REX software is licensed under a proprietary license or the GPL v.3.
* If you choose to receive it under the GPL v.3 license, the following applies:
* T-REX is a suite of smart contracts developed by Tokeny to manage and transfer financial assets on the ethereum blockchain
*
* Copyright (C) 2021, Tokeny sàrl.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
interface ITrustedIssuersRegistryLegacy {
/**
* this event is emitted when a trusted issuer is added in the registry.
* the event is emitted by the addTrustedIssuer function
* `trustedIssuer` is the address of the trusted issuer's ClaimIssuer contract
* `claimTopics` is the set of claims that the trusted issuer is allowed to emit
*/
event TrustedIssuerAdded(IClaimIssuerLegacy indexed trustedIssuer, uint256[] claimTopics);
/**
* this event is emitted when a trusted issuer is removed from the registry.
* the event is emitted by the removeTrustedIssuer function
* `trustedIssuer` is the address of the trusted issuer's ClaimIssuer contract
*/
event TrustedIssuerRemoved(IClaimIssuerLegacy indexed trustedIssuer);
/**
* this event is emitted when the set of claim topics is changed for a given trusted issuer.
* the event is emitted by the updateIssuerClaimTopics function
* `trustedIssuer` is the address of the trusted issuer's ClaimIssuer contract
* `claimTopics` is the set of claims that the trusted issuer is allowed to emit
*/
event ClaimTopicsUpdated(IClaimIssuerLegacy indexed trustedIssuer, uint256[] claimTopics);
/**
* @dev registers a ClaimIssuer contract as trusted claim issuer.
* Requires that a ClaimIssuer contract doesn't already exist
* Requires that the claimTopics set is not empty
* @param _trustedIssuer The ClaimIssuer contract address of the trusted claim issuer.
* @param _claimTopics the set of claim topics that the trusted issuer is allowed to emit
* This function can only be called by the owner of the Trusted Issuers Registry contract
* emits a `TrustedIssuerAdded` event
*/
function addTrustedIssuer(IClaimIssuerLegacy _trustedIssuer, uint256[] calldata _claimTopics) external;
/**
* @dev Removes the ClaimIssuer contract of a trusted claim issuer.
* Requires that the claim issuer contract to be registered first
* @param _trustedIssuer the claim issuer to remove.
* This function can only be called by the owner of the Trusted Issuers Registry contract
* emits a `TrustedIssuerRemoved` event
*/
function removeTrustedIssuer(IClaimIssuerLegacy _trustedIssuer) external;
/**
* @dev Updates the set of claim topics that a trusted issuer is allowed to emit.
* Requires that this ClaimIssuer contract already exists in the registry
* Requires that the provided claimTopics set is not empty
* @param _trustedIssuer the claim issuer to update.
* @param _claimTopics the set of claim topics that the trusted issuer is allowed to emit
* This function can only be called by the owner of the Trusted Issuers Registry contract
* emits a `ClaimTopicsUpdated` event
*/
function updateIssuerClaimTopics(IClaimIssuerLegacy _trustedIssuer, uint256[] calldata _claimTopics) external;
/**
* @dev Function for getting all the trusted claim issuers stored.
* @return array of all claim issuers registered.
*/
function getTrustedIssuers() external view returns (IClaimIssuerLegacy[] memory);
/**
* @dev Checks if the ClaimIssuer contract is trusted
* @param _issuer the address of the ClaimIssuer contract
* @return true if the issuer is trusted, false otherwise.
*/
function isTrustedIssuer(address _issuer) external view returns (bool);
/**
* @dev Function for getting all the claim topic of trusted claim issuer
* Requires the provided ClaimIssuer contract to be registered in the trusted issuers registry.
* @param _trustedIssuer the trusted issuer concerned.
* @return The set of claim topics that the trusted issuer is allowed to emit
*/
function getTrustedIssuerClaimTopics(IClaimIssuerLegacy _trustedIssuer) external view returns (uint256[] memory);
/**
* @dev Function for checking if the trusted claim issuer is allowed
* to emit a certain claim topic
* @param _issuer the address of the trusted issuer's ClaimIssuer contract
* @param _claimTopic the Claim Topic that has to be checked to know if the `issuer` is allowed to emit it
* @return true if the issuer is trusted for this claim topic.
*/
function hasClaimTopic(address _issuer, uint256 _claimTopic) external view returns (bool);
/**
* @dev Transfers the Ownership of TrustedIssuersRegistry to a new Owner.
* @param _newOwner The new owner of this contract.
* This function can only be called by the owner of the Trusted Issuers Registry contract
* emits an `OwnershipTransferred` event
*/
function transferOwnershipOnIssuersRegistryContract(address _newOwner) external;
}
// File: contracts/registry/IClaimTopicsRegistryLegacy.sol
/**
* NOTICE
*
* The T-REX software is licensed under a proprietary license or the GPL v.3.
* If you choose to receive it under the GPL v.3 license, the following applies:
* T-REX is a suite of smart contracts developed by Tokeny to manage and transfer financial assets on the ethereum blockchain
*
* Copyright (C) 2021, Tokeny sàrl.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
interface IClaimTopicsRegistryLegacy {
/**
* this event is emitted when a claim topic has been added to the ClaimTopicsRegistry
* the event is emitted by the 'addClaimTopic' function
* `claimTopic` is the required claim added to the Claim Topics Registry
*/
event ClaimTopicAdded(uint256 indexed claimTopic);
/**
* this event is emitted when a claim topic has been removed from the ClaimTopicsRegistry
* the event is emitted by the 'removeClaimTopic' function
* `claimTopic` is the required claim removed from the Claim Topics Registry
*/
event ClaimTopicRemoved(uint256 indexed claimTopic);
/**
* @dev Add a trusted claim topic (For example: KYC=1, AML=2).
* Only owner can call.
* emits `ClaimTopicAdded` event
* @param _claimTopic The claim topic index
*/
function addClaimTopic(uint256 _claimTopic) external;
/**
* @dev Remove a trusted claim topic (For example: KYC=1, AML=2).
* Only owner can call.
* emits `ClaimTopicRemoved` event
* @param _claimTopic The claim topic index
*/
function removeClaimTopic(uint256 _claimTopic) external;
/**
* @dev Get the trusted claim topics for the security token
* @return Array of trusted claim topics
*/
function getClaimTopics() external view returns (uint256[] memory);
/**
* @dev Transfers the Ownership of ClaimTopics to a new Owner.
* Only owner can call.
* @param _newOwner The new owner of this contract.
*/
function transferOwnershipOnClaimTopicsRegistryContract(address _newOwner) external;
}
// File: contracts/registry/IIdentityRegistryStorageLegacy.sol
/**
* NOTICE
*
* The T-REX software is licensed under a proprietary license or the GPL v.3.
* If you choose to receive it under the GPL v.3 license, the following applies:
* T-REX is a suite of smart contracts developed by Tokeny to manage and transfer financial assets on the ethereum blockchain
*
* Copyright (C) 2021, Tokeny sàrl.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
interface IIdentityRegistryStorageLegacy {
/**
* 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, LegacyIIdentity 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, LegacyIIdentity 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(LegacyIIdentity indexed oldIdentity, LegacyIIdentity 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 (LegacyIIdentity);
/**
* @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,
LegacyIIdentity _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, LegacyIIdentity _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;
}
// File: contracts/registry/IIdentityRegistryLegacy.sol
/**
* NOTICE
*
* The T-REX software is licensed under a proprietary license or the GPL v.3.
* If you choose to receive it under the GPL v.3 license, the following applies:
* T-REX is a suite of smart contracts developed by Tokeny to manage and transfer financial assets on the ethereum blockchain
*
* Copyright (C) 2021, Tokeny sàrl.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
interface IIdentityRegistryLegacy {
/**
* this event is emitted when the ClaimTopicsRegistry has been set for the IdentityRegistry
* the event is emitted by the IdentityRegistry constructor
* `claimTopicsRegistry` is the address of the Claim Topics Registry contract
*/
event ClaimTopicsRegistrySet(address indexed claimTopicsRegistry);
/**
* this event is emitted when the IdentityRegistryStorage has been set for the IdentityRegistry
* the event is emitted by the IdentityRegistry constructor
* `identityStorage` is the address of the Identity Registry Storage contract
*/
event IdentityStorageSet(address indexed identityStorage);
/**
* this event is emitted when the ClaimTopicsRegistry has been set for the IdentityRegistry
* the event is emitted by the IdentityRegistry constructor
* `trustedIssuersRegistry` is the address of the Trusted Issuers Registry contract
*/
event TrustedIssuersRegistrySet(address indexed trustedIssuersRegistry);
/**
* this event is emitted when an Identity is registered into the Identity Registry.
* 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 IdentityRegistered(address indexed investorAddress, LegacyIIdentity indexed identity);
/**
* this event is emitted when an Identity is removed from the Identity Registry.
* 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 IdentityRemoved(address indexed investorAddress, LegacyIIdentity 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 IdentityUpdated(LegacyIIdentity indexed oldIdentity, LegacyIIdentity 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 CountryUpdated(address indexed investorAddress, uint16 indexed country);
/**
* @dev Register an identity contract corresponding to a user address.
* Requires that the user doesn't have an identity contract already registered.
* This function can only be called by a wallet 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 `IdentityRegistered` event
*/
function registerIdentity(
address _userAddress,
LegacyIIdentity _identity,
uint16 _country
) external;
/**
* @dev Removes an user from the identity registry.
* Requires that the user have an identity contract already deployed that will be deleted.
* This function can only be called by a wallet set as agent of the smart contract
* @param _userAddress The address of the user to be removed
* emits `IdentityRemoved` event
*/
function deleteIdentity(address _userAddress) external;
/**
* @dev Replace the actual identityRegistryStorage contract with a new one.
* This function can only be called by the wallet set as owner of the smart contract
* @param _identityRegistryStorage The address of the new Identity Registry Storage
* emits `IdentityStorageSet` event
*/
function setIdentityRegistryStorage(address _identityRegistryStorage) external;
/**
* @dev Replace the actual claimTopicsRegistry contract with a new one.
* This function can only be called by the wallet set as owner of the smart contract
* @param _claimTopicsRegistry The address of the new claim Topics Registry
* emits `ClaimTopicsRegistrySet` event
*/
function setClaimTopicsRegistry(address _claimTopicsRegistry) external;
/**
* @dev Replace the actual trustedIssuersRegistry contract with a new one.
* This function can only be called by the wallet set as owner of the smart contract
* @param _trustedIssuersRegistry The address of the new Trusted Issuers Registry
* emits `TrustedIssuersRegistrySet` event
*/
function setTrustedIssuersRegistry(address _trustedIssuersRegistry) 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 a wallet set as agent of the smart contract
* @param _userAddress The address of the user
* @param _country The new country of the user
* emits `CountryUpdated` event
*/
function updateCountry(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 a wallet 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 `IdentityUpdated` event
*/
function updateIdentity(address _userAddress, LegacyIIdentity _identity) external;
/**
* @dev function allowing to register identities in batch
* This function can only be called by a wallet set as agent of the smart contract
* Requires that none of the users has an identity contract already registered.
* IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH,
* USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION
* @param _userAddresses The addresses of the users
* @param _identities The addresses of the corresponding identity contracts
* @param _countries The countries of the corresponding investors
* emits _userAddresses.length `IdentityRegistered` events
*/
function batchRegisterIdentity(
address[] calldata _userAddresses,
LegacyIIdentity[] calldata _identities,
uint16[] calldata _countries
) external;
/**
* @dev This functions checks whether a wallet has its Identity registered or not
* in the Identity Registry.
* @param _userAddress The address of the user to be checked.
* @return 'True' if the address is contained in the Identity Registry, 'false' if not.
*/
function contains(address _userAddress) external view returns (bool);
/**
* @dev This functions checks whether an identity contract
* corresponding to the provided user address has the required claims or not based
* on the data fetched from trusted issuers registry and from the claim topics registry
* @param _userAddress The address of the user to be verified.
* @return 'True' if the address is verified, 'false' if not.
*/
function isVerified(address _userAddress) external view returns (bool);
/**
* @dev Returns the onchainID of an investor.
* @param _userAddress The wallet of the investor
*/
function identity(address _userAddress) external view returns (LegacyIIdentity);
/**
* @dev Returns the country code of an investor.
* @param _userAddress The wallet of the investor
*/
function investorCountry(address _userAddress) external view returns (uint16);
/**
* @dev Returns the IdentityRegistryStorage linked to the current IdentityRegistry.
*/
function identityStorage() external view returns (IIdentityRegistryStorageLegacy);
/**
* @dev Returns the TrustedIssuersRegistry linked to the current IdentityRegistry.
*/
function issuersRegistry() external view returns (ITrustedIssuersRegistryLegacy);
/**
* @dev Returns the ClaimTopicsRegistry linked to the current IdentityRegistry.
*/
function topicsRegistry() external view returns (IClaimTopicsRegistryLegacy);
/**
* @notice Transfers the Ownership of the Identity Registry 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 transferOwnershipOnIdentityRegistryContract(address _newOwner) external;
/**
* @notice Adds an address as _agent of the Identity Registry Contract.
* This function can only be called by the wallet set as owner of the smart contract
* @param _agent The _agent's address to add.
*/
function addAgentOnIdentityRegistryContract(address _agent) external;
/**
* @notice Removes an address from being _agent of the Identity Registry Contract.
* This function can only be called by the wallet set as owner of the smart contract
* @param _agent The _agent's address to remove.
*/
function removeAgentOnIdentityRegistryContract(address _agent) external;
}
// File: contracts/compliance/IComplianceLegacy.sol
/**
* NOTICE
*
* The T-REX software is licensed under a proprietary license or the GPL v.3.
* If you choose to receive it under the GPL v.3 license, the following applies:
* T-REX is a suite of smart contracts developed by Tokeny to manage and transfer financial assets on the ethereum blockchain
*
* Copyright (C) 2021, Tokeny sàrl.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
interface IComplianceLegacy {
/**
* this event is emitted when the Agent has been added on the allowedList of this Compliance.
* the event is emitted by the Compliance constructor and by the addTokenAgent function
* `_agentAddress` is the address of the Agent to add
*/
event TokenAgentAdded(address _agentAddress);
/**
* this event is emitted when the Agent has been removed from the agent list of this Compliance.
* the event is emitted by the Compliance constructor and by the removeTokenAgent function
* `_agentAddress` is the address of the Agent to remove
*/
event TokenAgentRemoved(address _agentAddress);
/**
* this event is emitted when a token has been bound to the compliance contract
* the event is emitted by the bindToken function
* `_token` is the address of the token to bind
*/
event TokenBound(address _token);
/**
* this event is emitted when a token has been unbound from the compliance contract
* the event is emitted by the unbindToken function
* `_token` is the address of the token to unbind
*/
event TokenUnbound(address _token);
/**
* @dev Returns true if the Address is in the list of token agents
* @param _agentAddress address of this agent
*/
function isTokenAgent(address _agentAddress) external view returns (bool);
/**
* @dev Returns true if the address given corresponds to a token that is bound with the Compliance contract
* @param _token address of the token
*/
function isTokenBound(address _token) external view returns (bool);
/**
* @dev adds an agent to the list of token agents
* @param _agentAddress address of the agent to be added
* Emits a TokenAgentAdded event
*/
function addTokenAgent(address _agentAddress) external;
/**
* @dev remove Agent from the list of token agents
* @param _agentAddress address of the agent to be removed (must be added first)
* Emits a TokenAgentRemoved event
*/
function removeTokenAgent(address _agentAddress) external;
/**
* @dev binds a token to the compliance contract
* @param _token address of the token to bind
* Emits a TokenBound event
*/
function bindToken(address _token) external;
/**
* @dev unbinds a token from the compliance contract
* @param _token address of the token to unbind
* Emits a TokenUnbound event
*/
function unbindToken(address _token) external;
/**
* @dev checks that the transfer is compliant.
* default compliance always returns true
* READ ONLY FUNCTION, this function cannot be used to increment
* counters, emit events, ...
* @param _from The address of the sender
* @param _to The address of the receiver
* @param _amount The amount of tokens involved in the transfer
*/
function canTransfer(
address _from,
address _to,
uint256 _amount
) external view returns (bool);
/**
* @dev function called whenever tokens are transferred
* from one wallet to another
* this function can update state variables in the compliance contract
* these state variables being used by `canTransfer` to decide if a transfer
* is compliant or not depending on the values stored in these state variables and on
* the parameters of the compliance smart contract
* @param _from The address of the sender
* @param _to The address of the receiver
* @param _amount The amount of tokens involved in the transfer
*/
function transferred(
address _from,
address _to,
uint256 _amount
) external;
/**
* @dev function called whenever tokens are created
* on a wallet
* this function can update state variables in the compliance contract
* these state variables being used by `canTransfer` to decide if a transfer
* is compliant or not depending on the values stored in these state variables and on
* the parameters of the compliance smart contract
* @param _to The address of the receiver
* @param _amount The amount of tokens involved in the transfer
*/
function created(address _to, uint256 _amount) external;
/**
* @dev function called whenever tokens are destroyed
* this function can update state variables in the compliance contract
* these state variables being used by `canTransfer` to decide if a transfer
* is compliant or not depending on the values stored in these state variables and on
* the parameters of the compliance smart contract
* @param _from The address of the receiver
* @param _amount The amount of tokens involved in the transfer
*/
function destroyed(address _from, uint256 _amount) external;
/**
* @dev function used to transfer the ownership of the compliance contract
* to a new owner, giving him access to the `OnlyOwner` functions implemented on the contract
* @param newOwner The address of the new owner of the compliance contract
* This function can only be called by the owner of the compliance contract
* emits an `OwnershipTransferred` event
*/
function transferOwnershipOnComplianceContract(address newOwner) external;
}
// File: @openzeppelin/contracts/token/ERC20/IERC20Legacy.sol
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Legacy {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File: contracts/token/ITokenLegacy.sol
/**
* NOTICE
*
* The T-REX software is licensed under a proprietary license or the GPL v.3.
* If you choose to receive it under the GPL v.3 license, the following applies:
* T-REX is a suite of smart contracts developed by Tokeny to manage and transfer financial assets on the ethereum blockchain
*
* Copyright (C) 2021, Tokeny sàrl.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/// @dev interface
interface ITokenLegacy is IERC20Legacy {
/**
* this event is emitted when the token information is updated.
* the event is emitted by the token constructor and by the setTokenInformation function
* `_newName` is the name of the token
* `_newSymbol` is the symbol of the token
* `_newDecimals` is the decimals of the token
* `_newVersion` is the version of the token, current version is 3.0
* `_newOnchainID` is the address of the onchainID of the token
*/
event UpdatedTokenInformation(string _newName, string _newSymbol, uint8 _newDecimals, string _newVersion, address _newOnchainID);
/**
* this event is emitted when the IdentityRegistry has been set for the token
* the event is emitted by the token constructor and by the setIdentityRegistry function
* `_identityRegistry` is the address of the Identity Registry of the token
*/
event IdentityRegistryAdded(address indexed _identityRegistry);
/**
* this event is emitted when the Compliance has been set for the token
* the event is emitted by the token constructor and by the setCompliance function
* `_compliance` is the address of the Compliance contract of the token
*/
event ComplianceAdded(address indexed _compliance);
/**
* this event is emitted when an investor successfully recovers his tokens
* the event is emitted by the recoveryAddress function
* `_lostWallet` is the address of the wallet that the investor lost access to
* `_newWallet` is the address of the wallet that the investor provided for the recovery
* `_investorOnchainID` is the address of the onchainID of the investor who asked for a recovery
*/
event RecoverySuccess(address _lostWallet, address _newWallet, address _investorOnchainID);
/**
* this event is emitted when the wallet of an investor is frozen or unfrozen
* the event is emitted by setAddressFrozen and batchSetAddressFrozen functions
* `_userAddress` is the wallet of the investor that is concerned by the freezing status
* `_isFrozen` is the freezing status of the wallet
* if `_isFrozen` equals `true` the wallet is frozen after emission of the event
* if `_isFrozen` equals `false` the wallet is unfrozen after emission of the event
* `_owner` is the address of the agent who called the function to freeze the wallet
*/
event AddressFrozen(address indexed _userAddress, bool indexed _isFrozen, address indexed _owner);
/**
* this event is emitted when a certain amount of tokens is frozen on a wallet
* the event is emitted by freezePartialTokens and batchFreezePartialTokens functions
* `_userAddress` is the wallet of the investor that is concerned by the freezing status
* `_amount` is the amount of tokens that are frozen
*/
event TokensFrozen(address indexed _userAddress, uint256 _amount);
/**
* this event is emitted when a certain amount of tokens is unfrozen on a wallet
* the event is emitted by unfreezePartialTokens and batchUnfreezePartialTokens functions
* `_userAddress` is the wallet of the investor that is concerned by the freezing status
* `_amount` is the amount of tokens that are unfrozen
*/
event TokensUnfrozen(address indexed _userAddress, uint256 _amount);
/**
* this event is emitted when the token is paused
* the event is emitted by the pause function
* `_userAddress` is the address of the wallet that called the pause function
*/
event Paused(address _userAddress);
/**
* this event is emitted when the token is unpaused
* the event is emitted by the unpause function
* `_userAddress` is the address of the wallet that called the unpause function
*/
event Unpaused(address _userAddress);
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5,05` (`505 / 1 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* balanceOf() and transfer().
*/
function decimals() external view returns (uint8);
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the address of the onchainID of the token.
* the onchainID of the token gives all the information available
* about the token and is managed by the token issuer or his agent.
*/
function onchainID() external view returns (address);
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the TREX version of the token.
* current version is 3.0.0
*/
function version() external view returns (string memory);
/**
* @dev Returns the Identity Registry linked to the token
*/
function identityRegistry() external view returns (IIdentityRegistryLegacy);
/**
* @dev Returns the Compliance contract linked to the token
*/
function compliance() external view returns (IComplianceLegacy);
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() external view returns (bool);
/**
* @dev Returns the freezing status of a wallet
* if isFrozen returns `true` the wallet is frozen
* if isFrozen returns `false` the wallet is not frozen
* isFrozen returning `true` doesn't mean that the balance is free, tokens could be blocked by
* a partial freeze or the whole token could be blocked by pause
* @param _userAddress the address of the wallet on which isFrozen is called
*/
function isFrozen(address _userAddress) external view returns (bool);
/**
* @dev Returns the amount of tokens that are partially frozen on a wallet
* the amount of frozen tokens is always <= to the total balance of the wallet
* @param _userAddress the address of the wallet on which getFrozenTokens is called
*/
function getFrozenTokens(address _userAddress) external view returns (uint256);
/**
* @dev sets the token name
* @param _name the name of token to set
* Only the owner of the token smart contract can call this function
* emits a `UpdatedTokenInformation` event
*/
function setName(string calldata _name) external;
/**
* @dev sets the token symbol
* @param _symbol the token symbol to set
* Only the owner of the token smart contract can call this function
* emits a `UpdatedTokenInformation` event
*/
function setSymbol(string calldata _symbol) external;
/**
* @dev sets the onchain ID of the token
* @param _onchainID the address of the onchain ID to set
* Only the owner of the token smart contract can call this function
* emits a `UpdatedTokenInformation` event
*/
function setOnchainID(address _onchainID) external;
/**
* @dev pauses the token contract, when contract is paused investors cannot transfer tokens anymore
* This function can only be called by a wallet set as agent of the token
* emits a `Paused` event
*/
function pause() external;
/**
* @dev unpauses the token contract, when contract is unpaused investors can transfer tokens
* if their wallet is not blocked & if the amount to transfer is <= to the amount of free tokens
* This function can only be called by a wallet set as agent of the token
* emits an `Unpaused` event
*/
function unpause() external;
/**
* @dev sets an address frozen status for this token.
* @param _userAddress The address for which to update frozen status
* @param _freeze Frozen status of the address
* This function can only be called by a wallet set as agent of the token
* emits an `AddressFrozen` event
*/
function setAddressFrozen(address _userAddress, bool _freeze) external;
/**
* @dev freezes token amount specified for given address.
* @param _userAddress The address for which to update frozen tokens
* @param _amount Amount of Tokens to be frozen
* This function can only be called by a wallet set as agent of the token
* emits a `TokensFrozen` event
*/
function freezePartialTokens(address _userAddress, uint256 _amount) external;
/**
* @dev unfreezes token amount specified for given address
* @param _userAddress The address for which to update frozen tokens
* @param _amount Amount of Tokens to be unfrozen
* This function can only be called by a wallet set as agent of the token
* emits a `TokensUnfrozen` event
*/
function unfreezePartialTokens(address _userAddress, uint256 _amount) external;
/**
* @dev sets the Identity Registry for the token
* @param _identityRegistry the address of the Identity Registry to set
* Only the owner of the token smart contract can call this function
* emits an `IdentityRegistryAdded` event
*/
function setIdentityRegistry(address _identityRegistry) external;
/**
* @dev sets the compliance contract of the token
* @param _compliance the address of the compliance contract to set
* Only the owner of the token smart contract can call this function
* emits a `ComplianceAdded` event
*/
function setCompliance(address _compliance) external;
/**
* @dev force a transfer of tokens between 2 whitelisted wallets
* In case the `from` address has not enough free tokens (unfrozen tokens)
* but has a total balance higher or equal to the `amount`
* the amount of frozen tokens is reduced in order to have enough free tokens
* to proceed the transfer, in such a case, the remaining balance on the `from`
* account is 100% composed of frozen tokens post-transfer.
* Require that the `to` address is a verified address,
* @param _from The address of the sender
* @param _to The address of the receiver
* @param _amount The number of tokens to transfer
* @return `true` if successful and revert if unsuccessful
* This function can only be called by a wallet set as agent of the token
* emits a `TokensUnfrozen` event if `_amount` is higher than the free balance of `_from`
* emits a `Transfer` event
*/
function forcedTransfer(
address _from,
address _to,
uint256 _amount
) external returns (bool);
/**
* @dev mint tokens on a wallet
* Improved version of default mint method. Tokens can be minted
* to an address if only it is a verified address as per the security token.
* @param _to Address to mint the tokens to.
* @param _amount Amount of tokens to mint.
* This function can only be called by a wallet set as agent of the token
* emits a `Transfer` event
*/
function mint(address _to, uint256 _amount) external;
/**
* @dev burn tokens on a wallet
* In case the `account` address has not enough free tokens (unfrozen tokens)
* but has a total balance higher or equal to the `value` amount
* the amount of frozen tokens is reduced in order to have enough free tokens
* to proceed the burn, in such a case, the remaining balance on the `account`
* is 100% composed of frozen tokens post-transaction.
* @param _userAddress Address to burn the tokens from.
* @param _amount Amount of tokens to burn.
* This function can only be called by a wallet set as agent of the token
* emits a `TokensUnfrozen` event if `_amount` is higher than the free balance of `_userAddress`
* emits a `Transfer` event
*/
function burn(address _userAddress, uint256 _amount) external;
/**
* @dev recovery function used to force transfer tokens from a
* lost wallet to a new wallet for an investor.
* @param _lostWallet the wallet that the investor lost
* @param _newWallet the newly provided wallet on which tokens have to be transferred
* @param _investorOnchainID the onchainID of the investor asking for a recovery
* This function can only be called by a wallet set as agent of the token
* emits a `TokensUnfrozen` event if there is some frozen tokens on the lost wallet if the recovery process is successful
* emits a `Transfer` event if the recovery process is successful
* emits a `RecoverySuccess` event if the recovery process is successful
* emits a `RecoveryFails` event if the recovery process fails
*/
function recoveryAddress(
address _lostWallet,
address _newWallet,
address _investorOnchainID
) external returns (bool);
/**
* @dev function allowing to issue transfers in batch
* Require that the msg.sender and `to` addresses are not frozen.
* Require that the total value should not exceed available balance.
* Require that the `to` addresses are all verified addresses,
* IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_toList.length` IS TOO HIGH,
* USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION
* @param _toList The addresses of the receivers
* @param _amounts The number of tokens to transfer to the corresponding receiver
* emits _toList.length `Transfer` events
*/
function batchTransfer(address[] calldata _toList, uint256[] calldata _amounts) external;
/**
* @dev function allowing to issue forced transfers in batch
* Require that `_amounts[i]` should not exceed available balance of `_fromList[i]`.
* Require that the `_toList` addresses are all verified addresses
* IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_fromList.length` IS TOO HIGH,
* USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION
* @param _fromList The addresses of the senders
* @param _toList The addresses of the receivers
* @param _amounts The number of tokens to transfer to the corresponding receiver
* This function can only be called by a wallet set as agent of the token
* emits `TokensUnfrozen` events if `_amounts[i]` is higher than the free balance of `_fromList[i]`
* emits _fromList.length `Transfer` events
*/
function batchForcedTransfer(
address[] calldata _fromList,
address[] calldata _toList,
uint256[] calldata _amounts
) external;
/**
* @dev function allowing to mint tokens in batch
* Require that the `_toList` addresses are all verified addresses
* IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_toList.length` IS TOO HIGH,
* USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION
* @param _toList The addresses of the receivers
* @param _amounts The number of tokens to mint to the corresponding receiver
* This function can only be called by a wallet set as agent of the token
* emits _toList.length `Transfer` events
*/
function batchMint(address[] calldata _toList, uint256[] calldata _amounts) external;
/**
* @dev function allowing to burn tokens in batch
* Require that the `_userAddresses` addresses are all verified addresses
* IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH,
* USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION
* @param _userAddresses The addresses of the wallets concerned by the burn
* @param _amounts The number of tokens to burn from the corresponding wallets
* This function can only be called by a wallet set as agent of the token
* emits _userAddresses.length `Transfer` events
*/
function batchBurn(address[] calldata _userAddresses, uint256[] calldata _amounts) external;
/**
* @dev function allowing to set frozen addresses in batch
* IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH,
* USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION
* @param _userAddresses The addresses for which to update frozen status
* @param _freeze Frozen status of the corresponding address
* This function can only be called by a wallet set as agent of the token
* emits _userAddresses.length `AddressFrozen` events
*/
function batchSetAddressFrozen(address[] calldata _userAddresses, bool[] calldata _freeze) external;
/**
* @dev function allowing to freeze tokens partially in batch
* IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH,
* USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION
* @param _userAddresses The addresses on which tokens need to be frozen
* @param _amounts the amount of tokens to freeze on the corresponding address
* This function can only be called by a wallet set as agent of the token
* emits _userAddresses.length `TokensFrozen` events
*/
function batchFreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external;
/**
* @dev function allowing to unfreeze tokens partially in batch
* IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH,
* USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION
* @param _userAddresses The addresses on which tokens need to be unfrozen
* @param _amounts the amount of tokens to unfreeze on the corresponding address
* This function can only be called by a wallet set as agent of the token
* emits _userAddresses.length `TokensUnfrozen` events
*/
function batchUnfreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external;
/**
* @dev transfers the ownership of the token smart contract
* @param _newOwner the address of the new token smart contract owner
* This function can only be called by the owner of the token
* emits an `OwnershipTransferred` event
*/
function transferOwnershipOnTokenContract(address _newOwner) external;
/**
* @dev adds an agent to the token smart contract
* @param _agent the address of the new agent of the token smart contract
* This function can only be called by the owner of the token
* emits an `AgentAdded` event
*/
function addAgentOnTokenContract(address _agent) external;
/**
* @dev remove an agent from the token smart contract
* @param _agent the address of the agent to remove
* This function can only be called by the owner of the token
* emits an `AgentRemoved` event
*/
function removeAgentOnTokenContract(address _agent) external;
}
// File: contracts/token/Storage.sol
/**
* NOTICE
*
* The T-REX software is licensed under a proprietary license or the GPL v.3.
* If you choose to receive it under the GPL v.3 license, the following applies:
* T-REX is a suite of smart contracts developed by Tokeny to manage and transfer financial assets on the ethereum blockchain
*
* Copyright (C) 2021, Tokeny sàrl.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
contract TokenStorageLegacy {
/// @dev ERC20 basic variables
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) internal _allowances;
uint256 internal _totalSupply;
/// @dev Token information
string internal tokenName;
string internal tokenSymbol;
uint8 internal tokenDecimals;
address internal tokenOnchainID;
string internal constant TOKEN_VERSION = '3.5.1';
/// @dev Variables of freeze and pause functions
mapping(address => bool) internal frozen;
mapping(address => uint256) internal frozenTokens;
bool internal tokenPaused = false;
/// @dev Identity Registry contract used by the onchain validator system
IIdentityRegistryLegacy internal tokenIdentityRegistry;
/// @dev Compliance contract linked to the onchain validator system
IComplianceLegacy internal tokenCompliance;
}
// File: @openzeppelin/contracts-upgradeable/proxy/utils/InitializableLegacy.sol
// solhint-disable-next-line compiler-version
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
abstract contract InitializableLegacy {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || !_initialized, "InitializableLegacy: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}
// File: @openzeppelin/contracts-upgradeable/utils/ContextUpgradeableLegacy.sol
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeableLegacy is InitializableLegacy {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
uint256[50] private __gap;
}
// File: @openzeppelin/contracts-upgradeable/access/OwnableUpgradeableLegacy.sol
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeableLegacy is InitializableLegacy, ContextUpgradeableLegacy {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[49] private __gap;
}
// File: contracts/roles/RolesLegacy.sol
/**
* @title RolesLegacy
* @dev Library for managing addresses assigned to a Role.
*/
library RolesLegacy {
struct Role {
mapping(address => bool) bearer;
}
/**
* @dev Give an account access to this role.
*/
function add(Role storage role, address account) internal {
require(!has(role, account), 'RolesLegacy: account already has role');
role.bearer[account] = true;
}
/**
* @dev Remove an account's access to this role.
*/
function remove(Role storage role, address account) internal {
require(has(role, account), 'RolesLegacy: account does not have role');
role.bearer[account] = false;
}
/**
* @dev Check if an account has this role.
* @return bool
*/
function has(Role storage role, address account) internal view returns (bool) {
require(account != address(0), 'RolesLegacy: account is the zero address');
return role.bearer[account];
}
}
// File: contracts/roles/AgentRoleUpgradeableLegacy.sol
/**
* NOTICE
*
* The T-REX software is licensed under a proprietary license or the GPL v.3.
* If you choose to receive it under the GPL v.3 license, the following applies:
* T-REX is a suite of smart contracts developed by Tokeny to manage and transfer financial assets on the ethereum blockchain
*
* Copyright (C) 2021, Tokeny sàrl.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
contract AgentRoleUpgradeableLegacy is OwnableUpgradeableLegacy {
using RolesLegacy for RolesLegacy.Role;
event AgentAdded(address indexed _agent);
event AgentRemoved(address indexed _agent);
RolesLegacy.Role private _agents;
modifier onlyAgent() {
require(isAgent(msg.sender), 'AgentRole: caller does not have the Agent role');
_;
}
function isAgent(address _agent) public view returns (bool) {
return _agents.has(_agent);
}
function addAgent(address _agent) public onlyOwner {
_agents.add(_agent);
emit AgentAdded(_agent);
}
function removeAgent(address _agent) public onlyOwner {
_agents.remove(_agent);
emit AgentRemoved(_agent);
}
}
// File: contracts/token/Token.sol
/**
* NOTICE
*
* The T-REX software is licensed under a proprietary license or the GPL v.3.
* If you choose to receive it under the GPL v.3 license, the following applies:
* T-REX is a suite of smart contracts developed by Tokeny to manage and transfer financial assets on the ethereum blockchain
*
* Copyright (C) 2021, Tokeny sàrl.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
contract LegacyToken_3_5_2 is ITokenLegacy, AgentRoleUpgradeableLegacy, TokenStorageLegacy {
/**
* @dev the constructor initiates the token contract
* msg.sender is set automatically as the owner of the smart contract
* @param _identityRegistry the address of the Identity registry linked to the token
* @param _compliance the address of the compliance contract linked to the token
* @param _name the name of the token
* @param _symbol the symbol of the token
* @param _decimals the decimals of the token
* @param _onchainID the address of the onchainID of the token
* emits an `UpdatedTokenInformation` event
* emits an `IdentityRegistryAdded` event
* emits a `ComplianceAdded` event
*/
function init(
address _identityRegistry,
address _compliance,
string memory _name,
string memory _symbol,
uint8 _decimals,
address _onchainID
) public {
require(owner() == address(0), 'already initialized');
tokenName = _name;
tokenSymbol = _symbol;
tokenDecimals = _decimals;
tokenOnchainID = _onchainID;
tokenIdentityRegistry = IIdentityRegistryLegacy(_identityRegistry);
emit IdentityRegistryAdded(_identityRegistry);
tokenCompliance = IComplianceLegacy(_compliance);
emit ComplianceAdded(_compliance);
emit UpdatedTokenInformation(tokenName, tokenSymbol, tokenDecimals, TOKEN_VERSION, tokenOnchainID);
__Ownable_init();
}
/// @dev Modifier to make a function callable only when the contract is not paused.
modifier whenNotPaused() {
require(!tokenPaused, 'Pausable: paused');
_;
}
/// @dev Modifier to make a function callable only when the contract is paused.
modifier whenPaused() {
require(tokenPaused, 'Pausable: not paused');
_;
}
/**
* @dev See {IERC20Legacy-totalSupply}.
*/
function totalSupply() external view override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20Legacy-balanceOf}.
*/
function balanceOf(address _userAddress) public view override returns (uint256) {
return _balances[_userAddress];
}
/**
* @dev See {IERC20Legacy-allowance}.
*/
function allowance(address _owner, address _spender) external view virtual override returns (uint256) {
return _allowances[_owner][_spender];
}
/**
* @dev See {IERC20Legacy-approve}.
*/
function approve(address _spender, uint256 _amount) external virtual override returns (bool) {
_approve(msg.sender, _spender, _amount);
return true;
}
/**
* @dev See {ERC20-increaseAllowance}.
*/
function increaseAllowance(address _spender, uint256 _addedValue) external virtual returns (bool) {
_approve(msg.sender, _spender, _allowances[msg.sender][_spender] + (_addedValue));
return true;
}
/**
* @dev See {ERC20-decreaseAllowance}.
*/
function decreaseAllowance(address _spender, uint256 _subtractedValue) external virtual returns (bool) {
_approve(msg.sender, _spender, _allowances[msg.sender][_spender] - _subtractedValue);
return true;
}
/**
* @dev See {ERC20-_mint}.
*/
function _transfer(
address _from,
address _to,
uint256 _amount
) internal virtual {
require(_from != address(0), 'ERC20: transfer from the zero address');
require(_to != address(0), 'ERC20: transfer to the zero address');
_beforeTokenTransfer(_from, _to, _amount);
_balances[_from] = _balances[_from] - _amount;
_balances[_to] = _balances[_to] + _amount;
emit Transfer(_from, _to, _amount);
}
/**
* @dev See {ERC20-_mint}.
*/
function _mint(address _userAddress, uint256 _amount) internal virtual {
require(_userAddress != address(0), 'ERC20: mint to the zero address');
_beforeTokenTransfer(address(0), _userAddress, _amount);
_totalSupply = _totalSupply + _amount;
_balances[_userAddress] = _balances[_userAddress] + _amount;
emit Transfer(address(0), _userAddress, _amount);
}
/**
* @dev See {ERC20-_burn}.
*/
function _burn(address _userAddress, uint256 _amount) internal virtual {
require(_userAddress != address(0), 'ERC20: burn from the zero address');
_beforeTokenTransfer(_userAddress, address(0), _amount);
_balances[_userAddress] = _balances[_userAddress] - _amount;
_totalSupply = _totalSupply - _amount;
emit Transfer(_userAddress, address(0), _amount);
}
/**
* @dev See {ERC20-_approve}.
*/
function _approve(
address _owner,
address _spender,
uint256 _amount
) internal virtual {
require(_owner != address(0), 'ERC20: approve from the zero address');
require(_spender != address(0), 'ERC20: approve to the zero address');
_allowances[_owner][_spender] = _amount;
emit Approval(_owner, _spender, _amount);
}
/**
* @dev See {ERC20-_beforeTokenTransfer}.
*/
function _beforeTokenTransfer(
address _from,
address _to,
uint256 _amount
) internal virtual {}
/**
* @dev See {ITokenLegacy-decimals}.
*/
function decimals() external view override returns (uint8) {
return tokenDecimals;
}
/**
* @dev See {ITokenLegacy-name}.
*/
function name() external view override returns (string memory) {
return tokenName;
}
/**
* @dev See {ITokenLegacy-onchainID}.
*/
function onchainID() external view override returns (address) {
return tokenOnchainID;
}
/**
* @dev See {ITokenLegacy-symbol}.
*/
function symbol() external view override returns (string memory) {
return tokenSymbol;
}
/**
* @dev See {ITokenLegacy-version}.
*/
function version() external view override returns (string memory) {
return TOKEN_VERSION;
}
/**
* @dev See {ITokenLegacy-setName}.
*/
function setName(string calldata _name) external override onlyOwner {
tokenName = _name;
emit UpdatedTokenInformation(tokenName, tokenSymbol, tokenDecimals, TOKEN_VERSION, tokenOnchainID);
}
/**
* @dev See {ITokenLegacy-setSymbol}.
*/
function setSymbol(string calldata _symbol) external override onlyOwner {
tokenSymbol = _symbol;
emit UpdatedTokenInformation(tokenName, tokenSymbol, tokenDecimals, TOKEN_VERSION, tokenOnchainID);
}
/**
* @dev See {ITokenLegacy-setOnchainID}.
*/
function setOnchainID(address _onchainID) external override onlyOwner {
tokenOnchainID = _onchainID;
emit UpdatedTokenInformation(tokenName, tokenSymbol, tokenDecimals, TOKEN_VERSION, tokenOnchainID);
}
/**
* @dev See {ITokenLegacy-paused}.
*/
function paused() external view override returns (bool) {
return tokenPaused;
}
/**
* @dev See {ITokenLegacy-isFrozen}.
*/
function isFrozen(address _userAddress) external view override returns (bool) {
return frozen[_userAddress];
}
/**
* @dev See {ITokenLegacy-getFrozenTokens}.
*/
function getFrozenTokens(address _userAddress) external view override returns (uint256) {
return frozenTokens[_userAddress];
}
/**
* @notice ERC-20 overridden function that include logic to check for trade validity.
* Require that the msg.sender and to addresses are not frozen.
* Require that the value should not exceed available balance .
* Require that the to address is a verified address
* @param _to The address of the receiver
* @param _amount The number of tokens to transfer
* @return `true` if successful and revert if unsuccessful
*/
function transfer(address _to, uint256 _amount) public override whenNotPaused returns (bool) {
require(!frozen[_to] && !frozen[msg.sender], 'wallet is frozen');
require(_amount <= balanceOf(msg.sender) - (frozenTokens[msg.sender]), 'Insufficient Balance');
if (tokenIdentityRegistry.isVerified(_to) && tokenCompliance.canTransfer(msg.sender, _to, _amount)) {
tokenCompliance.transferred(msg.sender, _to, _amount);
_transfer(msg.sender, _to, _amount);
return true;
}
revert('Transfer not possible');
}
/**
* @dev See {ITokenLegacy-pause}.
*/
function pause() external override onlyAgent whenNotPaused {
tokenPaused = true;
emit Paused(msg.sender);
}
/**
* @dev See {ITokenLegacy-unpause}.
*/
function unpause() external override onlyAgent whenPaused {
tokenPaused = false;
emit Unpaused(msg.sender);
}
/**
* @dev See {ITokenLegacy-identityRegistry}.
*/
function identityRegistry() external view override returns (IIdentityRegistryLegacy) {
return tokenIdentityRegistry;
}
/**
* @dev See {ITokenLegacy-compliance}.
*/
function compliance() external view override returns (IComplianceLegacy) {
return tokenCompliance;
}
/**
* @dev See {ITokenLegacy-batchTransfer}.
*/
function batchTransfer(address[] calldata _toList, uint256[] calldata _amounts) external override {
for (uint256 i = 0; i < _toList.length; i++) {
transfer(_toList[i], _amounts[i]);
}
}
/**
* @notice ERC-20 overridden function that include logic to check for trade validity.
* Require that the from and to addresses are not frozen.
* Require that the value should not exceed available balance .
* Require that the to address is a verified address
* @param _from The address of the sender
* @param _to The address of the receiver
* @param _amount The number of tokens to transfer
* @return `true` if successful and revert if unsuccessful
*/
function transferFrom(
address _from,
address _to,
uint256 _amount
) external override whenNotPaused returns (bool) {
require(!frozen[_to] && !frozen[_from], 'wallet is frozen');
require(_amount <= balanceOf(_from) - (frozenTokens[_from]), 'Insufficient Balance');
if (tokenIdentityRegistry.isVerified(_to) && tokenCompliance.canTransfer(_from, _to, _amount)) {
tokenCompliance.transferred(_from, _to, _amount);
_transfer(_from, _to, _amount);
_approve(_from, msg.sender, _allowances[_from][msg.sender] - (_amount));
return true;
}
revert('Transfer not possible');
}
/**
* @dev See {ITokenLegacy-forcedTransfer}.
*/
function forcedTransfer(
address _from,
address _to,
uint256 _amount
) public override onlyAgent returns (bool) {
uint256 freeBalance = balanceOf(_from) - (frozenTokens[_from]);
if (_amount > freeBalance) {
uint256 tokensToUnfreeze = _amount - (freeBalance);
frozenTokens[_from] = frozenTokens[_from] - (tokensToUnfreeze);
emit TokensUnfrozen(_from, tokensToUnfreeze);
}
if (tokenIdentityRegistry.isVerified(_to)) {
tokenCompliance.transferred(_from, _to, _amount);
_transfer(_from, _to, _amount);
return true;
}
revert('Transfer not possible');
}
/**
* @dev See {ITokenLegacy-batchForcedTransfer}.
*/
function batchForcedTransfer(
address[] calldata _fromList,
address[] calldata _toList,
uint256[] calldata _amounts
) external override {
for (uint256 i = 0; i < _fromList.length; i++) {
forcedTransfer(_fromList[i], _toList[i], _amounts[i]);
}
}
/**
* @dev See {ITokenLegacy-mint}.
*/
function mint(address _to, uint256 _amount) public override onlyAgent {
require(tokenIdentityRegistry.isVerified(_to), 'Identity is not verified.');
require(tokenCompliance.canTransfer(msg.sender, _to, _amount), 'Compliance not followed');
_mint(_to, _amount);
tokenCompliance.created(_to, _amount);
}
/**
* @dev See {ITokenLegacy-batchMint}.
*/
function batchMint(address[] calldata _toList, uint256[] calldata _amounts) external override {
for (uint256 i = 0; i < _toList.length; i++) {
mint(_toList[i], _amounts[i]);
}
}
/**
* @dev See {ITokenLegacy-burn}.
*/
function burn(address _userAddress, uint256 _amount) public override onlyAgent {
uint256 freeBalance = balanceOf(_userAddress) - frozenTokens[_userAddress];
if (_amount > freeBalance) {
uint256 tokensToUnfreeze = _amount - (freeBalance);
frozenTokens[_userAddress] = frozenTokens[_userAddress] - (tokensToUnfreeze);
emit TokensUnfrozen(_userAddress, tokensToUnfreeze);
}
_burn(_userAddress, _amount);
tokenCompliance.destroyed(_userAddress, _amount);
}
/**
* @dev See {ITokenLegacy-batchBurn}.
*/
function batchBurn(address[] calldata _userAddresses, uint256[] calldata _amounts) external override {
for (uint256 i = 0; i < _userAddresses.length; i++) {
burn(_userAddresses[i], _amounts[i]);
}
}
/**
* @dev See {ITokenLegacy-setAddressFrozen}.
*/
function setAddressFrozen(address _userAddress, bool _freeze) public override onlyAgent {
frozen[_userAddress] = _freeze;
emit AddressFrozen(_userAddress, _freeze, msg.sender);
}
/**
* @dev See {ITokenLegacy-batchSetAddressFrozen}.
*/
function batchSetAddressFrozen(address[] calldata _userAddresses, bool[] calldata _freeze) external override {
for (uint256 i = 0; i < _userAddresses.length; i++) {
setAddressFrozen(_userAddresses[i], _freeze[i]);
}
}
/**
* @dev See {ITokenLegacy-freezePartialTokens}.
*/
function freezePartialTokens(address _userAddress, uint256 _amount) public override onlyAgent {
uint256 balance = balanceOf(_userAddress);
require(balance >= frozenTokens[_userAddress] + _amount, 'Amount exceeds available balance');
frozenTokens[_userAddress] = frozenTokens[_userAddress] + (_amount);
emit TokensFrozen(_userAddress, _amount);
}
/**
* @dev See {ITokenLegacy-batchFreezePartialTokens}.
*/
function batchFreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external override {
for (uint256 i = 0; i < _userAddresses.length; i++) {
freezePartialTokens(_userAddresses[i], _amounts[i]);
}
}
/**
* @dev See {ITokenLegacy-unfreezePartialTokens}.
*/
function unfreezePartialTokens(address _userAddress, uint256 _amount) public override onlyAgent {
require(frozenTokens[_userAddress] >= _amount, 'Amount should be less than or equal to frozen tokens');
frozenTokens[_userAddress] = frozenTokens[_userAddress] - (_amount);
emit TokensUnfrozen(_userAddress, _amount);
}
/**
* @dev See {ITokenLegacy-batchUnfreezePartialTokens}.
*/
function batchUnfreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external override {
for (uint256 i = 0; i < _userAddresses.length; i++) {
unfreezePartialTokens(_userAddresses[i], _amounts[i]);
}
}
/**
* @dev See {ITokenLegacy-setIdentityRegistry}.
*/
function setIdentityRegistry(address _identityRegistry) external override onlyOwner {
tokenIdentityRegistry = IIdentityRegistryLegacy(_identityRegistry);
emit IdentityRegistryAdded(_identityRegistry);
}
/**
* @dev See {ITokenLegacy-setCompliance}.
*/
function setCompliance(address _compliance) external override onlyOwner {
tokenCompliance = IComplianceLegacy(_compliance);
emit ComplianceAdded(_compliance);
}
/**
* @dev See {ITokenLegacy-recoveryAddress}.
*/
function recoveryAddress(
address _lostWallet,
address _newWallet,
address _investorOnchainID
) external override onlyAgent returns (bool) {
require(balanceOf(_lostWallet) != 0, 'no tokens to recover');
LegacyIIdentity _onchainID = LegacyIIdentity(_investorOnchainID);
bytes32 _key = keccak256(abi.encode(_newWallet));
if (_onchainID.keyHasPurpose(_key, 1)) {
uint256 investorTokens = balanceOf(_lostWallet);
uint256 _frozenTokens = frozenTokens[_lostWallet];
tokenIdentityRegistry.registerIdentity(_newWallet, _onchainID, tokenIdentityRegistry.investorCountry(_lostWallet));
tokenIdentityRegistry.deleteIdentity(_lostWallet);
forcedTransfer(_lostWallet, _newWallet, investorTokens);
if (_frozenTokens > 0) {
freezePartialTokens(_newWallet, _frozenTokens);
}
if (frozen[_lostWallet] == true) {
setAddressFrozen(_newWallet, true);
}
emit RecoverySuccess(_lostWallet, _newWallet, _investorOnchainID);
return true;
}
revert('Recovery not possible');
}
/**
* @dev See {ITokenLegacy-transferOwnershipOnTokenContract}.
*/
function transferOwnershipOnTokenContract(address _newOwner) external override onlyOwner {
transferOwnership(_newOwner);
}
/**
* @dev See {ITokenLegacy-addAgentOnTokenContract}.
*/
function addAgentOnTokenContract(address _agent) external override {
addAgent(_agent);
}
/**
* @dev See {ITokenLegacy-removeAgentOnTokenContract}.
*/
function removeAgentOnTokenContract(address _agent) external override {
removeAgent(_agent);
}
}