/** *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); } }