Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Resolver
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import {SchemaResolver} from "eas-contracts/resolver/SchemaResolver.sol";
import {IEAS, Attestation} from "eas-contracts/IEAS.sol";
import {IInvestorRegistry} from "src/interfaces/IInvestorRegistry.sol";
import "src/utils/Constant.sol";
/**
* @title Resolver
* @notice This contract handles the validation of the custom attestation data
* @dev The contract utilizes SchemaResolver for EAS-based attestation validation
* @author Kaio
*/
contract Resolver is SchemaResolver {
/// @notice Investor registry to manage investor-related data and credentials.
IInvestorRegistry public immutable investorRegistry;
constructor(IEAS eas, IInvestorRegistry _investorRegistry) SchemaResolver(eas) {
investorRegistry = _investorRegistry;
}
/**
* @notice Handles logic for attestation verification.
* @param _attestation The attestation data.
* @return Whether the attestation passes verification.
* @dev Includes credential validation by performing schema integrity and origin checks
*/
function onAttest(
Attestation calldata _attestation,
uint256 /*value*/
)
internal
view
override
returns (bool)
{
if (_attestation.attester != address(investorRegistry)) {
return false;
}
//Decode attestation schema
(, bytes32[] memory instrumentIds, uint64[] memory instrumentExpiryTimestamps) =
abi.decode(_attestation.data, (bytes32, bytes32[], uint64[]));
//Check the sizes of instrument list and their corresponding expiries are equal
if (instrumentIds.length != instrumentExpiryTimestamps.length) {
return false;
}
return true;
}
/**
* @notice Handles logic for attestation revocation.
* @return Always returns true as all revocation requests are allowed.
*/
function onRevoke(
Attestation calldata,
/*attestation*/
uint256 /*value*/
)
internal
pure
override
returns (bool)
{
return true;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import { AccessDenied, InvalidEAS, InvalidLength, uncheckedInc } from "./../Common.sol";
import { IEAS, Attestation } from "./../IEAS.sol";
import { Semver } from "./../Semver.sol";
import { ISchemaResolver } from "./ISchemaResolver.sol";
/// @title SchemaResolver
/// @notice The base schema resolver contract.
abstract contract SchemaResolver is ISchemaResolver, Semver {
error InsufficientValue();
error NotPayable();
// The global EAS contract.
IEAS internal immutable _eas;
/// @dev Creates a new resolver.
/// @param eas The address of the global EAS contract.
constructor(IEAS eas) Semver(1, 3, 0) {
if (address(eas) == address(0)) {
revert InvalidEAS();
}
_eas = eas;
}
/// @dev Ensures that only the EAS contract can make this call.
modifier onlyEAS() {
_onlyEAS();
_;
}
/// @inheritdoc ISchemaResolver
function isPayable() public pure virtual returns (bool) {
return false;
}
/// @dev ETH callback.
receive() external payable virtual {
if (!isPayable()) {
revert NotPayable();
}
}
/// @inheritdoc ISchemaResolver
function attest(Attestation calldata attestation) external payable onlyEAS returns (bool) {
return onAttest(attestation, msg.value);
}
/// @inheritdoc ISchemaResolver
function multiAttest(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable onlyEAS returns (bool) {
uint256 length = attestations.length;
if (length != values.length) {
revert InvalidLength();
}
// We are keeping track of the remaining ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint256 remainingValue = msg.value;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
// Ensure that the attester/revoker doesn't try to spend more than available.
uint256 value = values[i];
if (value > remainingValue) {
revert InsufficientValue();
}
// Forward the attestation to the underlying resolver and return false in case it isn't approved.
if (!onAttest(attestations[i], value)) {
return false;
}
unchecked {
// Subtract the ETH amount, that was provided to this attestation, from the global remaining ETH amount.
remainingValue -= value;
}
}
return true;
}
/// @inheritdoc ISchemaResolver
function revoke(Attestation calldata attestation) external payable onlyEAS returns (bool) {
return onRevoke(attestation, msg.value);
}
/// @inheritdoc ISchemaResolver
function multiRevoke(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable onlyEAS returns (bool) {
uint256 length = attestations.length;
if (length != values.length) {
revert InvalidLength();
}
// We are keeping track of the remaining ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint256 remainingValue = msg.value;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
// Ensure that the attester/revoker doesn't try to spend more than available.
uint256 value = values[i];
if (value > remainingValue) {
revert InsufficientValue();
}
// Forward the revocation to the underlying resolver and return false in case it isn't approved.
if (!onRevoke(attestations[i], value)) {
return false;
}
unchecked {
// Subtract the ETH amount, that was provided to this attestation, from the global remaining ETH amount.
remainingValue -= value;
}
}
return true;
}
/// @notice A resolver callback that should be implemented by child contracts.
/// @param attestation The new attestation.
/// @param value An explicit ETH amount that was sent to the resolver. Please note that this value is verified in
/// both attest() and multiAttest() callbacks EAS-only callbacks and that in case of multi attestations, it'll
/// usually hold that msg.value != value, since msg.value aggregated the sent ETH amounts for all the
/// attestations in the batch.
/// @return Whether the attestation is valid.
function onAttest(Attestation calldata attestation, uint256 value) internal virtual returns (bool);
/// @notice Processes an attestation revocation and verifies if it can be revoked.
/// @param attestation The existing attestation to be revoked.
/// @param value An explicit ETH amount that was sent to the resolver. Please note that this value is verified in
/// both revoke() and multiRevoke() callbacks EAS-only callbacks and that in case of multi attestations, it'll
/// usually hold that msg.value != value, since msg.value aggregated the sent ETH amounts for all the
/// attestations in the batch.
/// @return Whether the attestation can be revoked.
function onRevoke(Attestation calldata attestation, uint256 value) internal virtual returns (bool);
/// @dev Ensures that only the EAS contract can make this call.
function _onlyEAS() private view {
if (msg.sender != address(_eas)) {
revert AccessDenied();
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ISchemaRegistry } from "./ISchemaRegistry.sol";
import { ISemver } from "./ISemver.sol";
import { Attestation, Signature } from "./Common.sol";
/// @notice A struct representing the arguments of the attestation request.
struct AttestationRequestData {
address recipient; // The recipient of the attestation.
uint64 expirationTime; // The time when the attestation expires (Unix timestamp).
bool revocable; // Whether the attestation is revocable.
bytes32 refUID; // The UID of the related attestation.
bytes data; // Custom attestation data.
uint256 value; // An explicit ETH amount to send to the resolver. This is important to prevent accidental user errors.
}
/// @notice A struct representing the full arguments of the attestation request.
struct AttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData data; // The arguments of the attestation request.
}
/// @notice A struct representing the full arguments of the full delegated attestation request.
struct DelegatedAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData data; // The arguments of the attestation request.
Signature signature; // The ECDSA signature data.
address attester; // The attesting account.
uint64 deadline; // The deadline of the signature/request.
}
/// @notice A struct representing the full arguments of the multi attestation request.
struct MultiAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData[] data; // The arguments of the attestation request.
}
/// @notice A struct representing the full arguments of the delegated multi attestation request.
struct MultiDelegatedAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData[] data; // The arguments of the attestation requests.
Signature[] signatures; // The ECDSA signatures data. Please note that the signatures are assumed to be signed with increasing nonces.
address attester; // The attesting account.
uint64 deadline; // The deadline of the signature/request.
}
/// @notice A struct representing the arguments of the revocation request.
struct RevocationRequestData {
bytes32 uid; // The UID of the attestation to revoke.
uint256 value; // An explicit ETH amount to send to the resolver. This is important to prevent accidental user errors.
}
/// @notice A struct representing the full arguments of the revocation request.
struct RevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData data; // The arguments of the revocation request.
}
/// @notice A struct representing the arguments of the full delegated revocation request.
struct DelegatedRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData data; // The arguments of the revocation request.
Signature signature; // The ECDSA signature data.
address revoker; // The revoking account.
uint64 deadline; // The deadline of the signature/request.
}
/// @notice A struct representing the full arguments of the multi revocation request.
struct MultiRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData[] data; // The arguments of the revocation request.
}
/// @notice A struct representing the full arguments of the delegated multi revocation request.
struct MultiDelegatedRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData[] data; // The arguments of the revocation requests.
Signature[] signatures; // The ECDSA signatures data. Please note that the signatures are assumed to be signed with increasing nonces.
address revoker; // The revoking account.
uint64 deadline; // The deadline of the signature/request.
}
/// @title IEAS
/// @notice EAS - Ethereum Attestation Service interface.
interface IEAS is ISemver {
/// @notice Emitted when an attestation has been made.
/// @param recipient The recipient of the attestation.
/// @param attester The attesting account.
/// @param uid The UID of the new attestation.
/// @param schemaUID The UID of the schema.
event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID);
/// @notice Emitted when an attestation has been revoked.
/// @param recipient The recipient of the attestation.
/// @param attester The attesting account.
/// @param schemaUID The UID of the schema.
/// @param uid The UID the revoked attestation.
event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schemaUID);
/// @notice Emitted when a data has been timestamped.
/// @param data The data.
/// @param timestamp The timestamp.
event Timestamped(bytes32 indexed data, uint64 indexed timestamp);
/// @notice Emitted when a data has been revoked.
/// @param revoker The address of the revoker.
/// @param data The data.
/// @param timestamp The timestamp.
event RevokedOffchain(address indexed revoker, bytes32 indexed data, uint64 indexed timestamp);
/// @notice Returns the address of the global schema registry.
/// @return The address of the global schema registry.
function getSchemaRegistry() external view returns (ISchemaRegistry);
/// @notice Attests to a specific schema.
/// @param request The arguments of the attestation request.
/// @return The UID of the new attestation.
///
/// Example:
/// attest({
/// schema: "0facc36681cbe2456019c1b0d1e7bedd6d1d40f6f324bf3dd3a4cef2999200a0",
/// data: {
/// recipient: "0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf",
/// expirationTime: 0,
/// revocable: true,
/// refUID: "0x0000000000000000000000000000000000000000000000000000000000000000",
/// data: "0xF00D",
/// value: 0
/// }
/// })
function attest(AttestationRequest calldata request) external payable returns (bytes32);
/// @notice Attests to a specific schema via the provided ECDSA signature.
/// @param delegatedRequest The arguments of the delegated attestation request.
/// @return The UID of the new attestation.
///
/// Example:
/// attestByDelegation({
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: {
/// recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
/// expirationTime: 1673891048,
/// revocable: true,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x1234',
/// value: 0
/// },
/// signature: {
/// v: 28,
/// r: '0x148c...b25b',
/// s: '0x5a72...be22'
/// },
/// attester: '0xc5E8740aD971409492b1A63Db8d83025e0Fc427e',
/// deadline: 1673891048
/// })
function attestByDelegation(
DelegatedAttestationRequest calldata delegatedRequest
) external payable returns (bytes32);
/// @notice Attests to multiple schemas.
/// @param multiRequests The arguments of the multi attestation requests. The requests should be grouped by distinct
/// schema ids to benefit from the best batching optimization.
/// @return The UIDs of the new attestations.
///
/// Example:
/// multiAttest([{
/// schema: '0x33e9094830a5cba5554d1954310e4fbed2ef5f859ec1404619adea4207f391fd',
/// data: [{
/// recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
/// expirationTime: 1673891048,
/// revocable: true,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x1234',
/// value: 1000
/// },
/// {
/// recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
/// expirationTime: 0,
/// revocable: false,
/// refUID: '0x480df4a039efc31b11bfdf491b383ca138b6bde160988222a2a3509c02cee174',
/// data: '0x00',
/// value: 0
/// }],
/// },
/// {
/// schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425',
/// data: [{
/// recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
/// expirationTime: 0,
/// revocable: true,
/// refUID: '0x75bf2ed8dca25a8190c50c52db136664de25b2449535839008ccfdab469b214f',
/// data: '0x12345678',
/// value: 0
/// },
/// }])
function multiAttest(MultiAttestationRequest[] calldata multiRequests) external payable returns (bytes32[] memory);
/// @notice Attests to multiple schemas using via provided ECDSA signatures.
/// @param multiDelegatedRequests The arguments of the delegated multi attestation requests. The requests should be
/// grouped by distinct schema ids to benefit from the best batching optimization.
/// @return The UIDs of the new attestations.
///
/// Example:
/// multiAttestByDelegation([{
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: [{
/// recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
/// expirationTime: 1673891048,
/// revocable: true,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x1234',
/// value: 0
/// },
/// {
/// recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
/// expirationTime: 0,
/// revocable: false,
/// refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
/// data: '0x00',
/// value: 0
/// }],
/// signatures: [{
/// v: 28,
/// r: '0x148c...b25b',
/// s: '0x5a72...be22'
/// },
/// {
/// v: 28,
/// r: '0x487s...67bb',
/// s: '0x12ad...2366'
/// }],
/// attester: '0x1D86495b2A7B524D747d2839b3C645Bed32e8CF4',
/// deadline: 1673891048
/// }])
function multiAttestByDelegation(
MultiDelegatedAttestationRequest[] calldata multiDelegatedRequests
) external payable returns (bytes32[] memory);
/// @notice Revokes an existing attestation to a specific schema.
/// @param request The arguments of the revocation request.
///
/// Example:
/// revoke({
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: {
/// uid: '0x101032e487642ee04ee17049f99a70590c735b8614079fc9275f9dd57c00966d',
/// value: 0
/// }
/// })
function revoke(RevocationRequest calldata request) external payable;
/// @notice Revokes an existing attestation to a specific schema via the provided ECDSA signature.
/// @param delegatedRequest The arguments of the delegated revocation request.
///
/// Example:
/// revokeByDelegation({
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: {
/// uid: '0xcbbc12102578c642a0f7b34fe7111e41afa25683b6cd7b5a14caf90fa14d24ba',
/// value: 0
/// },
/// signature: {
/// v: 27,
/// r: '0xb593...7142',
/// s: '0x0f5b...2cce'
/// },
/// revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992',
/// deadline: 1673891048
/// })
function revokeByDelegation(DelegatedRevocationRequest calldata delegatedRequest) external payable;
/// @notice Revokes existing attestations to multiple schemas.
/// @param multiRequests The arguments of the multi revocation requests. The requests should be grouped by distinct
/// schema ids to benefit from the best batching optimization.
///
/// Example:
/// multiRevoke([{
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: [{
/// uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25',
/// value: 1000
/// },
/// {
/// uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade',
/// value: 0
/// }],
/// },
/// {
/// schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425',
/// data: [{
/// uid: '0x053d42abce1fd7c8fcddfae21845ad34dae287b2c326220b03ba241bc5a8f019',
/// value: 0
/// },
/// }])
function multiRevoke(MultiRevocationRequest[] calldata multiRequests) external payable;
/// @notice Revokes existing attestations to multiple schemas via provided ECDSA signatures.
/// @param multiDelegatedRequests The arguments of the delegated multi revocation attestation requests. The requests
/// should be grouped by distinct schema ids to benefit from the best batching optimization.
///
/// Example:
/// multiRevokeByDelegation([{
/// schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
/// data: [{
/// uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25',
/// value: 1000
/// },
/// {
/// uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade',
/// value: 0
/// }],
/// signatures: [{
/// v: 28,
/// r: '0x148c...b25b',
/// s: '0x5a72...be22'
/// },
/// {
/// v: 28,
/// r: '0x487s...67bb',
/// s: '0x12ad...2366'
/// }],
/// revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992',
/// deadline: 1673891048
/// }])
function multiRevokeByDelegation(
MultiDelegatedRevocationRequest[] calldata multiDelegatedRequests
) external payable;
/// @notice Timestamps the specified bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was timestamped with.
function timestamp(bytes32 data) external returns (uint64);
/// @notice Timestamps the specified multiple bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was timestamped with.
function multiTimestamp(bytes32[] calldata data) external returns (uint64);
/// @notice Revokes the specified bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was revoked with.
function revokeOffchain(bytes32 data) external returns (uint64);
/// @notice Revokes the specified multiple bytes32 data.
/// @param data The data to timestamp.
/// @return The timestamp the data was revoked with.
function multiRevokeOffchain(bytes32[] calldata data) external returns (uint64);
/// @notice Returns an existing attestation by UID.
/// @param uid The UID of the attestation to retrieve.
/// @return The attestation data members.
function getAttestation(bytes32 uid) external view returns (Attestation memory);
/// @notice Checks whether an attestation exists.
/// @param uid The UID of the attestation to retrieve.
/// @return Whether an attestation exists.
function isAttestationValid(bytes32 uid) external view returns (bool);
/// @notice Returns the timestamp that the specified data was timestamped with.
/// @param data The data to query.
/// @return The timestamp the data was timestamped with.
function getTimestamp(bytes32 data) external view returns (uint64);
/// @notice Returns the timestamp that the specified data was timestamped with.
/// @param data The data to query.
/// @return The timestamp the data was timestamped with.
function getRevokeOffchain(address revoker, bytes32 data) external view returns (uint64);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {
IERC20MetadataUpgradeable
} from "openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
import {IEAS, AttestationRequestData} from "eas-contracts/IEAS.sol";
import {IBaseRegistry} from "src/interfaces/IBaseRegistry.sol";
import {IRoleRegistry} from "src/interfaces/IRoleRegistry.sol";
import {IInstrumentRegistry} from "src/interfaces/IInstrumentRegistry.sol";
import {IDealerRegistry} from "src/interfaces/IDealerRegistry.sol";
import {IOperationsEngine} from "src/interfaces/IOperationsEngine.sol";
import {IUserRegistry} from "src/interfaces/IUserRegistry.sol";
import {IGatewayManager} from "src/interfaces/IGatewayManager.sol";
import {IEternalRegistryStorage} from "src/interfaces/IEternalRegistryStorage.sol";
import {InstrumentAccess} from "src/utils/Types.sol";
/**
* @title IInvestorRegistry
* @author Libre
* @notice Interface for managing investors, including adding new investors, managing credentials, and verifying subscriptions.
* It integrates with Ethereum Attestation Service (EAS) to ensure security and compliance.
*/
interface IInvestorRegistry is IBaseRegistry, IUserRegistry {
/// @notice Thrown when an operation is not permitted due to insufficient privileges.
error IInvestorRegistry_OperationNotPermitted();
/// @notice Thrown when the sender is not the dealer associated with the specified investor.
error IInvestorRegistry_NotInvestorsDealer();
/// @notice Thrown when the caller is not the Operations Engine.
error IInvestorRegistry_NotOperationsEngine();
/// @notice Thrown when the caller is not the Jurisdiction Registry.
error IInvestorRegistry_NotJurisdictionRegistry();
/// @notice Thrown when attempting to add an investor who is already registered.
error IInvestorRegistry_AlreadyAnInvestor();
/// @notice Thrown when the sender does not have the Contract Manager role.
error IInvestorRegistry_NoContractManagerRole();
/// @notice Thrown when the Resolver address is empty or invalid.
error IInvestorRegistry_EmptyResolver();
/// @notice Thrown when the sender does not have the Attester role.
error IInvestorRegistry_NoAttesterRole();
/// @notice Thrown when attempting to access a schema that has not been set.
error IInvestorRegistry_SchemaNotSet();
/// @notice Thrown when attempting to access a credential that does not exist.
error IInvestorRegistry_NonExistingCredential();
/// @notice Thrown when the credential is found to be invalid or revoked.
error IInvestorRegistry_CredentialInvalid();
/// @notice Thrown when the Investor Id doesn't match with the attestation's investor Id.
error IInvestorRegistry_MismatchInvestorId();
/// @notice Thrown when a credential does not grant access to the specified instrument.
error IInvestorRegistry_InstrumentCredentialInvalid();
/// @notice Thrown when attempting to revoke access to instruments that are not part of the credential.
error IInvestorRegistry_InstrumentsToRevokeNotInCredential();
/// @notice Thrown when an invalid dealer ID is provided.
error IInvestorRegistry_InvalidDealerId();
// Events
/**
* @notice Emitted when a new investor is added to the registry.
* @param investorId The unique identifier of the new investor.
* @param wallet The initial wallet address associated with the investor.
*/
event NewInvestorAdded(bytes32 investorId, address wallet);
/**
* @notice Emitted when a credential is set for an investor.
* @param investorId The unique identifier of the investor.
* @param instrumentIds The list of instrument IDs included in the credential.
*/
event InvestorRegistryCredentialSet(bytes32 investorId, bytes32[] instrumentIds);
/**
* @notice Emitted when a credential is revoked for an investor.
* @param investorId The unique identifier of the investor.
* @param instrumentIds The list of instrument IDs that have been revoked.
*/
event InvestorRegistryCredentialRevoked(bytes32 investorId, bytes32[] instrumentIds);
/**
* @notice Emitted when the Resolver is updated.
* @param resolverAddress The address of the new Resolver.
*/
event InvestorRegistryResolverChanged(address resolverAddress);
/**
* @notice Initialize the registry
* @param _roleRegistry Address of the Role Registry
* @param _instrumentRegistry Address of the Instrument Registry
* @param _dealerRegistry Address of the Dealer Registry
* @param _jurisdictionRegistry Address of the Jurisdiction Registry
* @param _operationsEngine Address of the Operations Engine
* @param _eas Address of the Ethereum Attestation Service contract
* @param _gatewayManager Address of the gateway manager contract
* @param _resolver Address of the EAS Resolver
*/
function initialize(
IRoleRegistry _roleRegistry,
IInstrumentRegistry _instrumentRegistry,
IDealerRegistry _dealerRegistry,
IEternalRegistryStorage _jurisdictionRegistry,
IOperationsEngine _operationsEngine,
IEAS _eas,
IGatewayManager _gatewayManager,
address _resolver
) external;
/**
* @notice Adds a new investor to the registry
* @param _senderRole Role the sender claims to have
* @param _investorId ID of the investor
* @param _wallet Default address of the investor
* @param _dealerId ID of the dealer
*/
function addInvestor(bytes32 _senderRole, bytes32 _investorId, address _wallet, bytes32 _dealerId) external;
/**
* @notice Replaces the Resolver contract with a new version, renewing the schema in the process
* @param _resolver address of the new resolver
*/
function configureResolver(address _resolver) external;
/**
* @notice Creates a new investor credential or updates an existing/revoked one
* @param _instrumentAccess contains data for setting the credential
* @dev When updating credential, the lists should contain new instruments to provide access to
*/
function setCredential(InstrumentAccess calldata _instrumentAccess) external;
/**
* @notice Revokes an investor credential, or access to certain instruments, bridge revoked credential via gateway manager
* @param _investorId Id of the investor
* @param _instrumentIds Instruments to revoke access from (entire credential revoked if left empty)
*/
function revokeCredential(bytes32 _investorId, bytes32[] calldata _instrumentIds) external;
/**
* @notice Checks if the investor has a valid credential
* @param _investorId Id of the investor
*/
function checkCredential(bytes32 _investorId) external view;
/**
* @notice Checks if the investor has a valid credential granting access to the instrument
* @param _investorId Id of the investor
* @param _instrumentId Id of the instrument
*/
function checkCredentialInstrument(bytes32 _investorId, bytes32 _instrumentId) external view;
/**
* @notice Checks if the investor has a valid credential granting access to the instrument for cross-chain operations
* @param _investorId Id of the investor
* @param _instrumentId Id of the instrument
* @dev Includes 1 day threshold validation for cross-chain operations
*/
function checkCredentialInstrumentForCrossChain(bytes32 _investorId, bytes32 _instrumentId) external view;
/**
* @notice Get dealer id of an investor
* @param _investorId The ID of the investor
* @return dealerId_ Id of the dealer associated to the investor
*/
function getDealer(bytes32 _investorId) external view returns (bytes32 dealerId_);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import "src/utils/JurisdictionEncodings.sol";
import "src/utils/Types.sol";
// General Config
bytes32 constant TIMEZONE = keccak256("TIMEZONE");
bytes32 constant MAX_TIMEZONE = keccak256("MAX_TIMEZONE");
// Chain/Gateway Config
uint16 constant NATIVE_CHAIN_SELECTOR = 101;
// NAV
bytes32 constant AUDITED_NAV_PER_SHARE = keccak256("AUDITED_NAV_PER_SHARE");
bytes32 constant INSTRUMENT_ALLOWED_ADDRESSES = keccak256("INSTRUMENT_ALLOWED_ADDRESSES");
// Volatility
bytes32 constant ANNUALIZED_VOLATILITY = keccak256("ANNUALIZED_VOLATILITY");
// Subscription Config
bytes32 constant SUBSCRIPTION_PHASES = keccak256("SUBSCRIPTION_PHASES");
bytes32 constant SUBSCRIPTION_START = keccak256("SUBSCRIPTION_START");
bytes32 constant SUBSCRIPTION_END = keccak256("SUBSCRIPTION_END");
bytes32 constant SUBSCRIPTION_FREQUENCY = keccak256("SUBSCRIPTION_FREQUENCY");
bytes32 constant SUBSCRIPTION_FREQUENCY_TIME_UNIT = keccak256("SUBSCRIPTION_FREQUENCY_TIME_UNIT");
// Redemption Config
bytes32 constant REDEMPTION_START = keccak256("REDEMPTION_START");
bytes32 constant REDEMPTION_END = keccak256("REDEMPTION_END");
bytes32 constant REDEMPTION_FREQUENCY = keccak256("REDEMPTION_FREQUENCY");
bytes32 constant REDEMPTION_FREQUENCY_TIME_UNIT = keccak256("REDEMPTION_FREQUENCY_TIME_UNIT");
// Fund data
bytes32 constant FUND_ID = keccak256("FUND_ID");
bytes32 constant DISCLOSURE_DOCUMENTS = keccak256("DISCLOSURE_DOCUMENTS");
bytes32 constant LISTED_ON_REGULATED_VENUE = keccak256("LISTED_ON_REGULATED_VENUE");
bytes32 constant LOCAL_AIFM = keccak256("LOCAL_AIFM");
bytes32 constant NON_EU_AIFM = keccak256("NON_EU_AIFM");
// Fund Instruments data
bytes32 constant INSTRUMENT_TOKEN = keccak256("INSTRUMENT_TOKEN");
bytes32 constant LOCAL_INVESTOR_MINIMUM_HOLDING = keccak256("LOCAL_INVESTOR_MINIMUM_HOLDING");
bytes32 constant AGGREGATED_MINIMUM_REDEMPTION_VALUE = keccak256("AGGREGATED_MINIMUM_REDEMPTION_VALUE");
bytes32 constant AGGREGATED_MINIMUM_SUBSEQUENT_SUBSCRIPTION = keccak256("AGGREGATED_MINIMUM_SUBSEQUENT_SUBSCRIPTION");
bytes32 constant INVESTOR_MINIMUM_INITIAL_SUBSCRIPTION = keccak256("INVESTOR_MINIMUM_INITIAL_SUBSCRIPTION");
bytes32 constant INVESTOR_MINIMUM_SUBSEQUENT_SUBSCRIPTION = keccak256("INVESTOR_MINIMUM_SUBSEQUENT_SUBSCRIPTION");
bytes32 constant REDEMPTION_BOOK = keccak256("REDEMPTION_BOOK");
bytes32 constant SUBSCRIPTION_BOOK = keccak256("SUBSCRIPTION_BOOK");
// Subscription Cutoff
bytes32 constant SUBSCRIPTION_CUT_OFF_CALENDAR_DAYS = keccak256("SUBSCRIPTION_CUT_OFF_CALENDAR_DAYS");
bytes32 constant SUBSCRIPTION_CUT_OFF_BUSINESS_DAYS = keccak256("SUBSCRIPTION_CUT_OFF_BUSINESS_DAYS");
bytes32 constant SUBSCRIPTION_CUT_OFF_TIME = keccak256("SUBSCRIPTION_CUT_OFF_TIME");
bytes32 constant SUBSCRIPTION_CUT_OFF_PERIOD = keccak256("SUBSCRIPTION_CUT_OFF_PERIOD");
bytes32 constant LOCAL_AGGREGATE_MINIMUM_HOLDING = keccak256("LOCAL_AGGREGATE_MINIMUM_HOLDING");
bytes32 constant SUBSCRIPTION_SIZE_MULTIPLE = keccak256("SUBSCRIPTION_SIZE_MULTIPLE");
bytes32 constant GLOBAL_AGGREGATE_MINIMUM_BREACH = keccak256("GLOBAL_AGGREGATE_MINIMUM_BREACH");
bytes32 constant FORCED_REDEMPTION_TOP_UP_PERIOD = keccak256("FORCED_REDEMPTION_TOP_UP_PERIOD");
bytes32 constant FORCED_REDEMPTION_TOP_UP_PERIOD_UNIT = keccak256("FORCED_REDEMPTION_TOP_UP_PERIOD_UNIT");
bytes32 constant REDEMPTION_VOLUME_LIMIT = keccak256("REDEMPTION_VOLUME_LIMIT");
bytes32 constant REDEMPTION_VOLUME_LIMIT_PER_INVESTOR = keccak256("REDEMPTION_VOLUME_LIMIT_PER_INVESTOR");
bytes32 constant REDEMPTION_VOLUME_LIMIT_PER_INVESTOR_FEE = keccak256("REDEMPTION_VOLUME_LIMIT_PER_INVESTOR_FEE");
bytes32 constant REDEMPTION_LOOKBACK_PERIOD = keccak256("REDEMPTION_LOOKBACK_PERIOD");
bytes32 constant REDEMPTION_LOOKBACK_PERIOD_UNIT = keccak256("REDEMPTION_LOOKBACK_PERIOD_UNIT");
bytes32 constant GATE_CRITERIA_1 = keccak256("GATE_CRITERIA_1");
bytes32 constant REDEMPTION_NOTICE_PERIOD = keccak256("REDEMPTION_NOTICE_PERIOD");
bytes32 constant REDEMPTION_NOTICE_PERIOD_UNIT = keccak256("REDEMPTION_NOTICE_PERIOD_UNIT");
bytes32 constant REDEMPTION_CUT_OFF_PERIOD = keccak256("REDEMPTION_CUT_OFF_PERIOD");
// Calendar
bytes32 constant BUSINESS_DAY_BITMAP_PART_1 = keccak256("BUSINESS_DAY_BITMAP_PART_1");
bytes32 constant BUSINESS_DAY_BITMAP_PART_2 = keccak256("BUSINESS_DAY_BITMAP_PART_2");
// Redemption Cutoff
bytes32 constant REDEMPTION_CUT_OFF_CALENDAR_DAYS = keccak256("REDEMPTION_CUT_OFF_CALENDAR_DAYS");
bytes32 constant REDEMPTION_CUT_OFF_BUSINESS_DAYS = keccak256("REDEMPTION_CUT_OFF_BUSINESS_DAYS");
bytes32 constant REDEMPTION_CUT_OFF_TIME = keccak256("REDEMPTION_CUT_OFF_TIME");
// Execution Date
bytes32 constant SUBSCRIPTION_NOTICE_PERIOD_CALENDAR_MONTHS = keccak256("SUBSCRIPTION_NOTICE_PERIOD_CALENDAR_MONTHS");
bytes32 constant SUBSCRIPTION_NOTICE_PERIOD_CALENDAR_DAYS = keccak256("SUBSCRIPTION_NOTICE_PERIOD_CALENDAR_DAYS");
bytes32 constant SUBSCRIPTION_NOTICE_PERIOD_BUSINESS_DAYS = keccak256("SUBSCRIPTION_NOTICE_PERIOD_BUSINESS_DAYS");
bytes32 constant SUBSCRIPTION_CUTOFF_TIME = keccak256("SUBSCRIPTION_CUTOFF_TIME");
bytes32 constant WAIVE_SUBSCRIPTION_NOTICE_PERIOD = keccak256("WAIVE_SUBSCRIPTION_NOTICE_PERIOD");
bytes32 constant SUBSCRIPTION_PREADJUSTMENT_DEALING_DAY_OF_MONTH =
keccak256("SUBSCRIPTION_PREADJUSTMENT_DEALING_DAY_OF_MONTH");
bytes32 constant REDEMPTION_NOTICE_PERIOD_CALENDAR_MONTHS = keccak256("REDEMPTION_NOTICE_PERIOD_CALENDAR_MONTHS");
bytes32 constant REDEMPTION_NOTICE_PERIOD_CALENDAR_DAYS = keccak256("REDEMPTION_NOTICE_PERIOD_CALENDAR_DAYS");
bytes32 constant REDEMPTION_NOTICE_PERIOD_BUSINESS_DAYS = keccak256("REDEMPTION_NOTICE_PERIOD_BUSINESS_DAYS");
bytes32 constant REDEMPTION_CUTOFF_TIME = keccak256("REDEMPTION_CUTOFF_TIME");
bytes32 constant WAIVE_REDEMPTION_NOTICE_PERIOD = keccak256("WAIVE_REDEMPTION_NOTICE_PERIOD");
bytes32 constant REDEMPTION_PREADJUSTMENT_DEALING_DAY_OF_MONTH =
keccak256("REDEMPTION_PREADJUSTMENT_DEALING_DAY_OF_MONTH");
// Redemption Holding Intervals
bytes32 constant REDEMPTION_FIRST_UNLOCK_PERIOD = keccak256("REDEMPTION_FIRST_UNLOCK_PERIOD");
bytes32 constant REDEMPTION_SECOND_UNLOCK_PERIOD = keccak256("REDEMPTION_SECOND_UNLOCK_PERIOD");
bytes32 constant CUMULATIVE_REDEMPTION_PERIOD = keccak256("CUMULATIVE_REDEMPTION_PERIOD");
bytes32 constant CUMULATIVE_REDEMPTION_PERIOD_UNIT = keccak256("CUMULATIVE_REDEMPTION_PERIOD_UNIT");
bytes32 constant CUMULATIVE_REDEMPTION_LIMIT_FEE = keccak256("CUMULATIVE_REDEMPTION_LIMIT_FEE");
bytes32 constant CUMULATIVE_REDEMPTION_LIMIT_ALLOWANCE = keccak256("CUMULATIVE_REDEMPTION_LIMIT_ALLOWANCE");
bytes32 constant CUMULATIVE_REDEMPTION_LIMIT_PER_INVESTOR_ALLOWANCE =
keccak256("CUMULATIVE_REDEMPTION_LIMIT_PER_INVESTOR_ALLOWANCE");
bytes32 constant CUMULATIVE_REDEMPTION_LIMIT_PER_INVESTOR_FEE =
keccak256("CUMULATIVE_REDEMPTION_LIMIT_PER_INVESTOR_FEE");
bytes32 constant INITIAL_REDEMPTION_RESTRICTED_PERIOD = keccak256("INITIAL_REDEMPTION_RESTRICTED_PERIOD");
bytes32 constant INITIAL_SUBSCRIPTION_RESTRICTED_PERIOD = keccak256("INITIAL_SUBSCRIPTION_RESTRICTED_PERIOD");
bytes32 constant INITIAL_SUBSCRIPTION_RESTRICTED_PERIOD_UNIT = keccak256("INITIAL_SUBSCRIPTION_RESTRICTED_PERIOD_UNIT");
bytes32 constant INITIAL_SUBSCRIPTION_RESTRICTED_PERIOD_ALLOWANCE =
keccak256("INITIAL_SUBSCRIPTION_RESTRICTED_PERIOD_ALLOWANCE");
bytes32 constant INITIAL_SUBSCRIPTION_RESTRICTED_PERIOD_FEE = keccak256("INITIAL_SUBSCRIPTION_RESTRICTED_PERIOD_FEE");
bytes32 constant INITIAL_REDEMPTION_RESTRICTED_PERIOD_ALLOWANCE =
keccak256("INITIAL_REDEMPTION_RESTRICTED_PERIOD_ALLOWANCE");
bytes32 constant POST_SUBSCRIPTION_RESTRICTED_PERIOD_ALLOWANCE =
keccak256("POST_SUBSCRIPTION_RESTRICTED_PERIOD_ALLOWANCE");
bytes32 constant POST_SUBSCRIPTION_RESTRICTED_PERIOD_FEE = keccak256("POST_SUBSCRIPTION_RESTRICTED_PERIOD_FEE");
bytes32 constant INITIAL_REDEMPTION_RESTRICTED_PERIOD_FEE = keccak256("INITIAL_REDEMPTION_RESTRICTED_PERIOD_FEE");
bytes32 constant POST_REDEMPTION_RESTRICTED_PERIOD_ALLOWANCE = keccak256("POST_REDEMPTION_RESTRICTED_PERIOD_ALLOWANCE");
bytes32 constant POST_REDEMPTION_RESTRICTED_PERIOD_FEE = keccak256("POST_REDEMPTION_RESTRICTED_PERIOD_FEE");
bytes32 constant GLOBAL_AGGREGATE_MINIMUM_HOLDING = keccak256("GLOBAL_AGGREGATE_MINIMUM_HOLDING");
bytes32 constant BLOCKED = keccak256("BLOCKED");
bytes32 constant RESIDENCES_ALLOWED = keccak256("RESIDENCES_ALLOWED");
bytes32 constant NATIONALITIES_ALLOWED = keccak256("NATIONALITIES_ALLOWED");
bytes32 constant INVESTOR_TYPES_ALLOWED = keccak256("INVESTOR_TYPES_ALLOWED");
bytes32 constant ESTIMATED_REDEMPTION_FEE = keccak256("ESTIMATED_REDEMPTION_FEE");
bytes32 constant IS_INVESTOR_ALLOWED = keccak256("IS_INVESTOR_ALLOWED");
bytes32 constant HOLDING_FEE = keccak256("HOLDING_FEE");
bytes32 constant HOLDING_FEE_PERIOD = keccak256("HOLDING_FEE_PERIOD");
bytes32 constant HOLDING_FEE_PERIOD_UNIT = keccak256("HOLDING_FEE_PERIOD_UNIT");
// Investors data
bytes32 constant INVESTOR_TYPE = keccak256("INVESTOR_TYPE");
bytes32 constant MAX_INVESTOR_TYPE = keccak256("MAX_INVESTOR_TYPE");
bytes32 constant NATIONALITIES = keccak256("NATIONALITIES");
bytes32 constant REVIEW_DATE = keccak256("REVIEW_DATE");
bytes32 constant KYC_PASSED = keccak256("KYC_PASSED");
bytes32 constant AML_PASSED = keccak256("AML_PASSED");
bytes32 constant SANCTIONS_PASSED = keccak256("SANCTIONS_PASSED");
bytes32 constant SELF_CERTIFICATION = keccak256("SELF_CERTIFICATION");
bytes32 constant FITNESS_TEST = keccak256("FITNESS_TEST");
bytes32 constant FROZEN = keccak256("FROZEN");
bytes32 constant USA_STATE = keccak256("USA_STATE");
bytes32 constant ALLOWED_TO_INTERACT_DAY = keccak256("ALLOWED_TO_INTERACT_DAY");
bytes32 constant DEALER = keccak256("DEALER");
bytes32 constant REVERSE_ENQUIRY = keccak256("REVERSE_ENQUIRY");
// Jurisdictions data
bytes32 constant JURISDICTION_ALLOWED = keccak256("JURISDICTION_ALLOWED");
bytes32 constant INVESTOR_ALLOWLISTED_REQUIRED = keccak256("INVESTOR_ALLOWLISTED_REQUIRED");
bytes32 constant SELF_CERTIFICATION_REQUIRED = keccak256("SELF_CERTIFICATION_REQUIRED");
bytes32 constant FITNESS_TEST_REQUIRED = keccak256("FITNESS_TEST_REQUIRED");
bytes32 constant DISCLOSURE_DOCUMENTS_REQUIRED = keccak256("DISCLOSURE_DOCUMENTS_REQUIRED");
bytes32 constant LISTED_ON_REGULATED_VENUE_REQUIRED = keccak256("LISTED_ON_REGULATED_VENUE_REQUIRED");
bytes32 constant LOCAL_AIFM_REQUIRED = keccak256("LOCAL_AIFM_REQUIRED");
bytes32 constant NON_EU_AIFM_REQUIRED = keccak256("NON_EU_AIFM_REQUIRED");
bytes32 constant MINIMUM_INVESTMENT_REQUIRED = keccak256("MINIMUM_INVESTMENT_REQUIRED");
bytes32 constant MINIMUM_INVESTMENT = keccak256("MINIMUM_INVESTMENT");
bytes32 constant NO_MINIMUM_INVESTMENT_HOLDER_NUMBER = keccak256("NO_MINIMUM_INVESTMENT_HOLDER_NUMBER");
// Registries
bytes32 constant GENERAL_DATA_ID = bytes32(0);
bytes32 constant ETERNAL_STORAGE_SLOT = keccak256("ETERNAL_STORAGE_SLOT");
bytes32 constant BLACKLISTED_WALLET = keccak256("BLACKLISTED_WALLET");
// Tracking
bytes32 constant CURRENT_SUBSCRIPTIONS_AMOUNT = keccak256("CURRENT_SUBSCRIPTIONS_AMOUNT");
bytes32 constant INVESTOR_SUBSCRIPTION_AMOUNT = keccak256("INVESTOR_SUBSCRIPTION_AMOUNT");
bytes32 constant CURRENT_REDEMPTIONS_AMOUNT = keccak256("CURRENT_REDEMPTIONS_AMOUNT");
bytes32 constant INVESTOR_REDEMPTION_AMOUNT = keccak256("INVESTOR_REDEMPTION_AMOUNT");
bytes32 constant REDEMPTION_RECORDS = keccak256("REDEMPTION_RECORDS");
bytes32 constant REDEMPTION_RECORDS_COUNT = keccak256("REDEMPTION_RECORDS_COUNT");
bytes32 constant REDEMPTION_RECORDS_AGGREGATE = keccak256("REDEMPTION_RECORDS_AGGREGATE");
bytes32 constant REDEMPTION_RECORDS_TIMESTAMP = keccak256("REDEMPTION_RECORDS_TIMESTAMP");
bytes32 constant HOLDING_FEE_EXEMPTION_CREDITS = keccak256("HOLDING_FEE_EXEMPTION_CREDITS");
bytes32 constant HOLDING_FEE_EXEMPTION_CREDITS_START = keccak256("HOLDING_FEE_EXEMPTION_CREDITS_START");
bytes32 constant HOLDING_FEE_EXEMPTION_CREDITS_COUNT = keccak256("HOLDING_FEE_EXEMPTION_CREDITS_COUNT");
bytes32 constant HOLDING_FEE_EXEMPTION_CREDITS_AMOUNT = keccak256("HOLDING_FEE_EXEMPTION_CREDITS_AMOUNT");
bytes32 constant HOLDING_FEE_EXEMPTION_CREDITS_TIMESTAMP = keccak256("HOLDING_FEE_EXEMPTION_CREDITS_TIMESTAMP");
bytes32 constant RTV_HOLDING_FEE_EXEMPTION_CREDITS = keccak256("RTV_HOLDING_FEE_EXEMPTION_CREDITS");
bytes32 constant RTV_HOLDING_FEE_EXEMPTION_CREDITS_START = keccak256("RTV_HOLDING_FEE_EXEMPTION_CREDITS_START");
bytes32 constant RTV_HOLDING_FEE_EXEMPTION_CREDITS_COUNT = keccak256("RTV_HOLDING_FEE_EXEMPTION_CREDITS_COUNT");
bytes32 constant RTV_HOLDING_FEE_EXEMPTION_CREDITS_AMOUNT = keccak256("RTV_HOLDING_FEE_EXEMPTION_CREDITS_AMOUNT");
bytes32 constant RTV_HOLDING_FEE_EXEMPTION_CREDITS_TIMESTAMP = keccak256("RTV_HOLDING_FEE_EXEMPTION_CREDITS_TIMESTAMP");
bytes32 constant AAVE_HORIZON_HOLDING_FEE_EXEMPTION_CREDITS = keccak256("AAVE_HORIZON_HOLDING_FEE_EXEMPTION_CREDITS");
bytes32 constant AAVE_HORIZON_HOLDING_FEE_EXEMPTION_CREDITS_START =
keccak256("AAVE_HORIZON_HOLDING_FEE_EXEMPTION_CREDITS_START");
bytes32 constant AAVE_HORIZON_HOLDING_FEE_EXEMPTION_CREDITS_COUNT =
keccak256("AAVE_HORIZON_HOLDING_FEE_EXEMPTION_CREDITS_COUNT");
bytes32 constant AAVE_HORIZON_HOLDING_FEE_EXEMPTION_CREDITS_AMOUNT =
keccak256("AAVE_HORIZON_HOLDING_FEE_EXEMPTION_CREDITS_AMOUNT");
bytes32 constant AAVE_HORIZON_HOLDING_FEE_EXEMPTION_CREDITS_TIMESTAMP =
keccak256("AAVE_HORIZON_HOLDING_FEE_EXEMPTION_CREDITS_TIMESTAMP");
bytes32 constant AAVE_HORIZON_ATOKEN_ADDRESS = keccak256("AAVE_HORIZON_ATOKEN_ADDRESS");
bytes32 constant AAVE_HORIZON_ATOKEN_PARKED_BALANCE = keccak256("AAVE_HORIZON_ATOKEN_PARKED_BALANCE");
bytes32 constant GATEWAY_HOLDING_FEE_EXEMPTION_CREDITS = keccak256("GATEWAY_HOLDING_FEE_EXEMPTION_CREDITS");
bytes32 constant GATEWAY_HOLDING_FEE_EXEMPTION_CREDITS_START = keccak256("GATEWAY_HOLDING_FEE_EXEMPTION_CREDITS_START");
bytes32 constant GATEWAY_HOLDING_FEE_EXEMPTION_CREDITS_COUNT = keccak256("GATEWAY_HOLDING_FEE_EXEMPTION_CREDITS_COUNT");
bytes32 constant GATEWAY_HOLDING_FEE_EXEMPTION_CREDITS_AMOUNT =
keccak256("GATEWAY_HOLDING_FEE_EXEMPTION_CREDITS_AMOUNT");
bytes32 constant GATEWAY_HOLDING_FEE_EXEMPTION_CREDITS_TIMESTAMP =
keccak256("GATEWAY_HOLDING_FEE_EXEMPTION_CREDITS_TIMESTAMP");
// Tracking (Holding Intervals)
bytes32 constant HOLDING_TIME_CREDITS = keccak256("HOLDING_TIME_CREDITS");
bytes32 constant HOLDING_TIME_CREDITS_START = keccak256("HOLDING_TIME_CREDITS_START");
bytes32 constant HOLDING_TIME_CREDITS_COUNT = keccak256("HOLDING_TIME_CREDITS_COUNT");
bytes32 constant HOLDING_TIME_CREDITS_TIMESTAMP = keccak256("HOLDING_TIME_CREDITS_TIMESTAMP");
bytes32 constant HOLDING_CREDITS_FIRST_PERIOD = keccak256("HOLDING_CREDITS_FIRST_PERIOD"); // related to REDEMPTION_FIRST_UNLOCK_PERIOD
bytes32 constant HOLDING_CREDITS_SECOND_PERIOD = keccak256("HOLDING_CREDITS_SECOND_PERIOD"); // related to REDEMPTION_SECOND_UNLOCK_PERIOD
bytes32 constant HOLDING_PERCENTAGE_FIRST_PERIOD = keccak256("HOLDING_PERCENTAGE_FIRST_PERIOD");
bytes32 constant HOLDING_PERCENTAGE_SECOND_PERIOD = keccak256("HOLDING_PERCENTAGE_SECOND_PERIOD");
// Tracking (NAV Track Module)
bytes32 constant NAV_NUM_CHECKPOINTS = keccak256("NAV_NUM_CHECKPOINTS");
bytes32 constant NAV_CHECKPOINT = keccak256("NAV_CHECKPOINT");
bytes32 constant NAV_CHECKPOINT_TIMESTAMP = keccak256("NAV_CHECKPOINT_TIMESTAMP");
// Security Token Track (Per investor)
bytes32 constant SECURITY_TOKEN_NUM_CHECKPOINTS = keccak256("SECURITY_TOKEN_NUM_CHECKPOINTS");
bytes32 constant SECURITY_TOKEN_CHECKPOINT_TIMESTAMP = keccak256("SECURITY_TOKEN_CHECKPOINT_TIMESTAMP");
bytes32 constant SECURITY_TOKEN_CHECKPOINTS = keccak256("SECURITY_TOKEN_CHECKPOINTS");
// Investor Registry
bytes32 constant IS_INVESTOR = keccak256("IS_INVESTOR");
bytes32 constant LAST_OPERATION_TIMESTAMP = keccak256("LAST_OPERATION_TIMESTAMP");
bytes32 constant CREDENTIAL_ID = keccak256("CREDENTIAL_ID");
bytes32 constant INVESTOR_CROSS_CHAIN_ADDRESSES = keccak256("INVESTOR_CROSS_CHAIN_ADDRESSES");
// Instrument Registry
bytes32 constant IS_INSTRUMENT = keccak256("IS_INSTRUMENT");
bytes32 constant TRADING_DAYS_IN_YEAR = keccak256("TRADING_DAYS_IN_YEAR");
bytes32 constant INSTRUMENT_INITIALIZED = keccak256("INSTRUMENT_INITIALIZED");
bytes32 constant INSTRUMENT_CLOSED = keccak256("INSTRUMENT_CLOSED");
bytes32 constant INSTANT_SETTLEMENT = keccak256("INSTANT_SETTLEMENT");
bytes32 constant CAN_TRANSFER_SETTLEMENT_TOKEN = keccak256("CAN_TRANSFER_SETTLEMENT_TOKEN");
bytes32 constant CAN_TRANSFER_SECURITY_TOKEN = keccak256("CAN_TRANSFER_SECURITY_TOKEN");
bytes32 constant INSTRUMENT_PAUSED = keccak256("INSTRUMENT_PAUSED");
// Dealer Registry
bytes32 constant IS_DEALER = keccak256("IS_DEALER");
// Fund Registry
bytes32 constant IS_FUND = keccak256("IS_FUND");
bytes32 constant DEFAULT_FUND_MODULES = keccak256("DEFAULT_FUND_MODULES");
// Roles
bytes32 constant DEFAULT_ADMIN_ROLE = bytes32(0);
bytes32 constant DEALER_MANAGER_ROLE = keccak256("DEALER_MANAGER_ROLE");
bytes32 constant LIBRE_DEALER_ROLE = keccak256("LIBRE_DEALER_ROLE");
bytes32 constant INSTRUMENT_MANAGER_ROLE = keccak256("INSTRUMENT_MANAGER_ROLE");
bytes32 constant SETTLEMENT_TOKEN_MINTER_ROLE = keccak256("SETTLEMENT_TOKEN_MINTER_ROLE");
bytes32 constant SETTLEMENT_TOKEN_BURNER_ROLE = keccak256("SETTLEMENT_TOKEN_BURNER_ROLE");
bytes32 constant RELAYER_ROLE = keccak256("RELAYER_ROLE");
bytes32 constant CONTRACT_MANAGER_ROLE = keccak256("CONTRACT_MANAGER_ROLE");
bytes32 constant REGISTRY_WRITER_ROLE_ADMIN = keccak256("REGISTRY_WRITER_ROLE_ADMIN");
bytes32 constant REGISTRY_WRITER_ROLE = keccak256("REGISTRY_WRITER_ROLE");
bytes32 constant ATTESTER_ROLE = keccak256("ATTESTER_ROLE");
bytes32 constant GATEWAY_MANAGER_ROLE = keccak256("GATEWAY_MANAGER_ROLE");
bytes32 constant CORE_GATEWAY_ROLE = keccak256("CORE_GATEWAY_ROLE");
bytes32 constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE");
bytes32 constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
// Hash of module names
bytes32 constant TRANSFER_MODULE = keccak256("TransferModule");
bytes32 constant DAILY_EXECUTION_CALCULATOR_MODULE = keccak256("DailyExecutionCalculatorModule");
bytes32 constant EXECUTION_DATE_ENFORCEMENT_MODULE = keccak256("ExecutionDateEnforcementModule");
bytes32 constant HALT_MODULE = keccak256("HaltModule");
bytes32 constant HOLDINGS_MODULE = keccak256("HoldingsModule");
bytes32 constant MONTHLY_EXECUTION_CALCULATOR_MODULE = keccak256("MonthlyExecutionCalculatorModule");
bytes32 constant FORCED_REDEMPTION_MODULE = keccak256("ForcedRedemptionModule");
bytes32 constant GATE_1_MODULE = keccak256("Gate1Module");
bytes32 constant HOLDING_INTERVALS_MODULE = keccak256("HoldingIntervalsModule");
bytes32 constant REDEMPTIONS_AGGREGATION_LIMIT_MODULE = keccak256("RedemptionsAggregationLimitModule");
bytes32 constant SUBSCRIPTIONS_AGGREGATION_LIMIT_MODULE = keccak256("SubscriptionsAggregationLimitModule");
bytes32 constant HOLDING_FEE_MODULE = keccak256("HoldingFeeModule");
bytes32 constant REDEMPTION_VOLUME_LIMIT_PER_INVESTOR_FEE_MODULE =
keccak256("RedemptionVolumeLimitPerInvestorFeeModule");
bytes32 constant INVESTOR_LAST_OPERATION_TRACKING_MODULE = keccak256("InvestorLastOperationTrackingModule");
bytes32 constant NAV_TRACKING_MODULE = keccak256("NAVTrackingModule");
bytes32 constant REDEMPTIONS_RECORDS_MODULE = keccak256("RedemptionsRecordsModule");
bytes32 constant REDEMPTIONS_TOTAL_AMOUNT_MODULE = keccak256("RedemptionsTotalAmountModule");
bytes32 constant SECURITY_TOKEN_TRACKING_MODULE = keccak256("SecurityTokenTrackingModule");
bytes32 constant SUBSCRIPTIONS_TOTAL_AMOUNT_MODULE = keccak256("SubscriptionsTotalAmountModule");
bytes32 constant HOLDING_FEE_EXEMPTION_MODULE = keccak256("HoldingFeeExemptionModule");
bytes32 constant HOLDING_INTERVALS_TRACKING_MODULE = keccak256("HoldingIntervalsTrackingModule");
bytes32 constant HOLDING_FEE_RECEIPT_TOKEN_VAULT_EXEMPTION_MODULE =
keccak256("HoldingFeeReceiptTokenVaultExemptionModule");
bytes32 constant HOLDING_FEE_AAVE_HORIZON_EXEMPTION_MODULE = keccak256("HoldingFeeAaveHorizonExemptionModule");
bytes32 constant AAVE_HORIZON_CONFIG_CHECK_MODULE = keccak256("AaveHorizonConfigCheckModule");
bytes32 constant HOLDING_FEE_GATEWAY_EXEMPTION_MODULE = keccak256("HoldingFeeGatewayExemptionModule");
// Percentage calculations
uint256 constant PERCENTAGE_BASE = 100_00;
// Cross-chain threshold time (1 day) for credential expiry validation
uint256 constant CROSS_CHAIN_THRESHOLD_TIME = 1 days;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// A representation of an empty/uninitialized UID.
bytes32 constant EMPTY_UID = 0;
// A zero expiration represents an non-expiring attestation.
uint64 constant NO_EXPIRATION_TIME = 0;
error AccessDenied();
error DeadlineExpired();
error InvalidEAS();
error InvalidLength();
error InvalidSignature();
error NotFound();
/// @notice A struct representing ECDSA signature data.
struct Signature {
uint8 v; // The recovery ID.
bytes32 r; // The x-coordinate of the nonce R.
bytes32 s; // The signature data.
}
/// @notice A struct representing a single attestation.
struct Attestation {
bytes32 uid; // A unique identifier of the attestation.
bytes32 schema; // The unique identifier of the schema.
uint64 time; // The time when the attestation was created (Unix timestamp).
uint64 expirationTime; // The time when the attestation expires (Unix timestamp).
uint64 revocationTime; // The time when the attestation was revoked (Unix timestamp).
bytes32 refUID; // The UID of the related attestation.
address recipient; // The recipient of the attestation.
address attester; // The attester/sender of the attestation.
bool revocable; // Whether the attestation is revocable.
bytes data; // Custom attestation data.
}
/// @notice A helper function to work with unchecked iterators in loops.
function uncheckedInc(uint256 i) pure returns (uint256 j) {
unchecked {
j = i + 1;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { ISemver } from "./ISemver.sol";
/// @title Semver
/// @notice A simple contract for managing contract versions.
contract Semver is ISemver {
// Contract's major version number.
uint256 private immutable _major;
// Contract's minor version number.
uint256 private immutable _minor;
// Contract's patch version number.
uint256 private immutable _patch;
/// @dev Create a new Semver instance.
/// @param major Major version number.
/// @param minor Minor version number.
/// @param patch Patch version number.
constructor(uint256 major, uint256 minor, uint256 patch) {
_major = major;
_minor = minor;
_patch = patch;
}
/// @notice Returns the full semver contract version.
/// @return Semver contract version as a string.
function version() external view returns (string memory) {
return
string(
abi.encodePacked(Strings.toString(_major), ".", Strings.toString(_minor), ".", Strings.toString(_patch))
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Attestation } from "./../Common.sol";
import { ISemver } from "./../ISemver.sol";
/// @title ISchemaResolver
/// @notice The interface of an optional schema resolver.
interface ISchemaResolver is ISemver {
/// @notice Checks if the resolver can be sent ETH.
/// @return Whether the resolver supports ETH transfers.
function isPayable() external pure returns (bool);
/// @notice Processes an attestation and verifies whether it's valid.
/// @param attestation The new attestation.
/// @return Whether the attestation is valid.
function attest(Attestation calldata attestation) external payable returns (bool);
/// @notice Processes multiple attestations and verifies whether they are valid.
/// @param attestations The new attestations.
/// @param values Explicit ETH amounts which were sent with each attestation.
/// @return Whether all the attestations are valid.
function multiAttest(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable returns (bool);
/// @notice Processes an attestation revocation and verifies if it can be revoked.
/// @param attestation The existing attestation to be revoked.
/// @return Whether the attestation can be revoked.
function revoke(Attestation calldata attestation) external payable returns (bool);
/// @notice Processes revocation of multiple attestation and verifies they can be revoked.
/// @param attestations The existing attestations to be revoked.
/// @param values Explicit ETH amounts which were sent with each revocation.
/// @return Whether the attestations can be revoked.
function multiRevoke(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ISemver } from "./ISemver.sol";
import { ISchemaResolver } from "./resolver/ISchemaResolver.sol";
/// @notice A struct representing a record for a submitted schema.
struct SchemaRecord {
bytes32 uid; // The unique identifier of the schema.
ISchemaResolver resolver; // Optional schema resolver.
bool revocable; // Whether the schema allows revocations explicitly.
string schema; // Custom specification of the schema (e.g., an ABI).
}
/// @title ISchemaRegistry
/// @notice The interface of global attestation schemas for the Ethereum Attestation Service protocol.
interface ISchemaRegistry is ISemver {
/// @notice Emitted when a new schema has been registered
/// @param uid The schema UID.
/// @param registerer The address of the account used to register the schema.
/// @param schema The schema data.
event Registered(bytes32 indexed uid, address indexed registerer, SchemaRecord schema);
/// @notice Submits and reserves a new schema
/// @param schema The schema data schema.
/// @param resolver An optional schema resolver.
/// @param revocable Whether the schema allows revocations explicitly.
/// @return The UID of the new schema.
function register(string calldata schema, ISchemaResolver resolver, bool revocable) external returns (bytes32);
/// @notice Returns an existing schema by UID
/// @param uid The UID of the schema to retrieve.
/// @return The schema data members.
function getSchema(bytes32 uid) external view returns (SchemaRecord memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title ISemver
/// @notice A semver interface.
interface ISemver {
/// @notice Returns the full semver contract version.
/// @return Semver contract version as a string.
function version() external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.19;
import "../IERC20Upgradeable.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IEternalRegistryStorage} from "src/interfaces/IEternalRegistryStorage.sol";
/**
* @title IBaseRegistry
* @notice Interface for the base registry, which provides functionality for tracking and retrieving data
* specific to modules that interact with the registry.
* @dev The tracked data can be queried via a delegatecall callback to the relevant module,
* which implements the query logic.
*/
interface IBaseRegistry is IEternalRegistryStorage {
/**
* @notice Thrown when an unauthorized caller tries to access a restricted function or resource.
*/
error IBaseRegistry_AccessDenied();
/**
* @notice Thrown when an action is attempted on a module that is not registered in the registry.
*/
error IBaseRegistry_NotRegisteredModule();
/**
* @notice Thrown when an invalid or non-existent ID is provided for an operation.
*/
error IBaseRegistry_NotAValidId();
/**
* @notice Thrown when the system fails to retrieve the tracked data for a specific operation or ID.
*/
error IBaseRegistry_FailedToGetTrackedData();
/**
* @notice Get the tracked data of the registry
* @param _data Data to be used by the module to get the tracked data
* @return bytes memory of the tracked data
* @dev This function is used to get the tracked data from the registry
* by doing a delegatecall callback to the module requesting the data
* which can implement the query logic
*/
function getTrackedData(bytes memory _data) external returns (bytes memory);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {
IAccessControlUpgradeable
} from "openzeppelin-contracts-upgradeable/contracts/access/IAccessControlUpgradeable.sol";
/**
* @title Roles Registry
* @author Libre
* @notice Store all the roles of the system as well as the permissions a user get by having each role.
* @dev It is meant to be used for roles access validation in all the components of the system.
*/
interface IRoleRegistry is IAccessControlUpgradeable {
/**
* @notice Thrown when attempting to create a role that already exists.
*/
error IRoleRegistry_RoleAlreadyExists();
/**
* @notice Thrown when attempting to grant a role that does not exist.
*/
error IRoleRegistry_RoleDoesNotExist();
/**
* @notice Thrown when attempting to use a blacklisted wallet.
*/
error IRoleRegistry_WalletBlacklisted();
/**
* @notice Used when a new role is created
* @param _role Parent role
* @param _subRole Newly created Role
*/
event RoleCreated(bytes32 _role, bytes32 _subRole);
/**
* @notice Used when a contract manager is set
* @param _contract Contract managed
* @param _roleManager New contract manager role
*/
event ContractManagerAdded(address _contract, bytes32 _roleManager);
/**
* @notice Used when a wallet is blacklisted
* @param _wallet Wallet blacklisted
*/
event WalletBlacklisted(address _wallet);
/**
* @notice Used when a contract function access is granted
* @param _contract Contract managed
* @param _selector Selector of the funtion which access is modified
* @param _role Role getting access gratend
*/
event AccessGranted(address _contract, bytes4 _selector, bytes32 _role);
/**
* @notice Used when a contract function access is revoked
* @param _contract Contract managed
* @param _selector Selector of the funtion which access is modified
* @param _role Role which access is revoked
*/
event RevokedAccess(address _contract, bytes4 _selector, bytes32 _role);
/**
* @notice Used when a contract access is reset
* @param _contract Contract managed
* @param _timestamp Time when the reset is executed
*/
event ResetedAccess(address _contract, uint256 _timestamp);
/**
* @notice Function to create subroles
* @param _role New role to create
* @param _adminRole Parent role of the newly created role
* @dev Caller needs to has role _adminRole
*/
function createRole(bytes32 _role, bytes32 _adminRole) external;
/**
* @notice Set the role going to manage permissions in a specific contract
* @param _contract Address of the contract to where permissions are needed to be managed
* @param _roleManager Role in charge of managing the permissions
*/
function setContractManager(address _contract, bytes32 _roleManager) external;
/**
* @notice Get the role that manages permissions in a specific contract
* @param _contract Address of the contract
*/
function getContractManager(address _contract) external view returns (bytes32);
/**
* @notice Grant a role the right access a functionality of a contract
* @param _contract Contract where the access is granted
* @param _selector Functionality granted access for
* @param _role Role getting the access
*/
function grantAccess(address _contract, bytes4 _selector, bytes32 _role) external;
/**
* @notice Prevent a role for having access to a functionality of a contract
* @param _contract Contract where the access is revoked
* @param _selector Functionality revoked access for
* @param _role Role losing the access
*/
function revokeAccess(address _contract, bytes4 _selector, bytes32 _role) external;
/**
* @notice Revoke access to a functionality of a contract for all roles
* @param _contract Contract where the access is reset
* @param _selector Functionality reset access for
* @dev Cleans all the previously granted roles
*/
function resetAccess(address _contract, bytes4 _selector) external;
/**
* @notice Blacklists a wallet.
* @param _wallet The wallet to blacklist.
*/
function blacklistWallet(address _wallet) external;
/**
* @notice Check access of a role to a contract functionality
* @param _contract Contract where accessed
* @param _selector Functionality accessed
* @param _requestor Address attempting to access
* @param _role Role of the address attempting to access
*/
function hasAccess(address _contract, bytes4 _selector, address _requestor, bytes32 _role)
external
view
returns (bool);
/**
* @notice Checks if a wallet is blacklisted.
* @param _wallet The wallet to check.
* @return Boolean indicating whether the wallet is blacklisted.
*/
function isBlacklisted(address _wallet) external view returns (bool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {IBaseRegistry} from "src/interfaces/IBaseRegistry.sol";
import {IDealerRegistry} from "src/interfaces/IDealerRegistry.sol";
import {IFundRegistry} from "src/interfaces/IFundRegistry.sol";
import {IRoleRegistry} from "src/interfaces/IRoleRegistry.sol";
import {IInvestorRegistry} from "src/interfaces/IInvestorRegistry.sol";
import {IOperationsEngine} from "src/interfaces/IOperationsEngine.sol";
import {IEternalRegistryStorage} from "src/interfaces/IEternalRegistryStorage.sol";
/**
* @title IInstrumentRegistry
* @author Libre
* @notice Interface for managing instruments within a fund registry system.
* Provides functionalities to initialize, add, and manage instruments, track their subscription and redemption periods,
* update Net Asset Value (NAV) per share, and manage investor access.
*/
interface IInstrumentRegistry is IBaseRegistry {
/**
* @notice Thrown when attempting to add an instrument that already exists in the registry.
*/
error IInstrumentRegistry_InstrumentAlreadyExists();
/**
* @notice Thrown when the specified instrument does not exist in the registry.
*/
error IInstrumentRegistry_InstrumentDoesNotExist();
/**
* @notice Thrown when attempting to initialize an instrument that has already been initialized.
*/
error IInstrumentRegistry_InstrumentAlreadyInitialized();
/**
* @notice Emited when a new instrument is added
* @param fundId Id of the fund where the instrument is added
* @param instrumentId Id of the new instrument
*/
event NewFundInstrumentAdded(bytes32 indexed fundId, bytes32 indexed instrumentId);
/**
* @notice Emited when an instrument is initialized
* @param instrumentId Id of the new instrument
* @param settlementToken Address of the settlement token of the instrument
* @param securityToken Address of the deployed security token
* @param subscriptionBook Address of the deployed subscription book
* @param redemptionBook Address of the deployed redemption book
*/
event FundInstrumentInitialized(
bytes32 indexed instrumentId,
address settlementToken,
address securityToken,
address subscriptionBook,
address redemptionBook
);
/**
* @notice Emited when an instrument is closed
* @param instrumentId Id of the instrument
*/
event InstrumentClosed(bytes32 indexed instrumentId);
/**
* @notice Emited when an instrument is paused
* @param instrumentId Id of the instrument
* @param paused Y/N value indicating if the instrument is paused or not
*/
event InstrumentPaused(bytes32 indexed instrumentId, bool paused);
/**
* @notice Emited when an investor's allowlist status is updated for an instrument
* @param instrumentId Id of the instrument
* @param investorId Id of the investor
* @param allowed Y/N value indicating if the investor is allowed or not
*/
event InvestorAllowedUpdated(bytes32 indexed instrumentId, bytes32 indexed investorId, bool allowed);
/**
* @notice Initialize the registry
* @param _roleRegistry Address of the Role Registry
* @param _investorRegistry Address of the Investor Registry
* @param _dealerRegistry Address of the Dealer Registry
* @param _fundRegistry Address of the Fund Registry
* @param _jurisdictionRegistry Address of the Jurisdiction Registry
* @param _operationsEngine Address of the Rules Engine
*/
function initialize(
IRoleRegistry _roleRegistry,
IInvestorRegistry _investorRegistry,
IDealerRegistry _dealerRegistry,
IFundRegistry _fundRegistry,
IEternalRegistryStorage _jurisdictionRegistry,
IOperationsEngine _operationsEngine
) external;
/**
* @notice Adds a new fund instrument to the registry
* @dev _senderRole is ignored if the caller if the Fund Admin of the instrument
* @param _senderRole Role of the sender which allow the operation execution
* @param _instrumentId the instrument ID
* @param _fundId the fund ID
*/
function addFundInstrument(bytes32 _senderRole, bytes32 _instrumentId, bytes32 _fundId) external;
/**
* @notice Adds a new instrument to the registry
* @dev _senderRole is ignored if the caller if the Fund Admin of the instrument
* @param _senderRole Role of the sender which allow the operation execution
* @param _instrumentId the instrument ID
* @param _settlementToken settlement token address
* @param _name the instrument token name
* @param _symbol the instrument token symbol
* @param _subscriptionBookImp The implementation of subscription book to be cloned
* @param _redemptionBookImp The implementation of redemption book to be cloned
* @param _stTokenImpl The implementation of security token implementation to be cloned
* @param _treasury The address of instrument treasury
*/
function initializeFundInstrument(
bytes32 _senderRole,
bytes32 _fundId,
bytes32 _instrumentId,
address _settlementToken,
string memory _name,
string memory _symbol,
address _subscriptionBookImp,
address _redemptionBookImp,
address _stTokenImpl,
address _treasury
) external;
/**
* @notice Close a fund instrument
* @param _senderRole Role of the sender which allow the operation execution
* @param _instrumentId The ID of the instrument
*/
function closeFundInstrument(bytes32 _senderRole, bytes32 _instrumentId) external;
/**
* @notice Return the number of the current subscription period or
* 0 in case subscription is not started or infinite if subscriptions are done
* @dev Infinite is represented by type(uint256).max;
* @param _instrumentId Id of the instrument
* @return The current period of the subscription, the start & the end of it
*/
function currentSubscriptionPeriod(bytes32 _instrumentId) external view returns (uint256, uint256, uint256);
/**
* @notice Return the number of the current redemption period or
* 0 in case redemption is not started or infinite if redemptions are done
* @param _instrumentId Id of the instrument
* @return The current period of the redemption, the start & the end of it
*/
function currentRedemptionPeriod(bytes32 _instrumentId) external view returns (uint256, uint256, uint256);
/**
* @notice Sets a new value for the audited NAV per share of a fund
* @param _senderRole Role of the sender which allow the operation execution
* @param _instrumentId ID of the fund
* @param _newNavPerShare new value of the nav
* @dev Expressed with 6 decimals as it is in settlement tokens units
*/
function updateAuditedNavPerShare(bytes32 _senderRole, bytes32 _instrumentId, uint256 _newNavPerShare) external;
/**
* @notice Allow investor for a specific instrument
* @param _instrumentId The ID of the instrument
* @param _investorId Id of the investor
* @param _allowed Y/N value indicating if the investor is allowed or not
* @param _senderRole Role of the sender
*/
function allowInvestor(bytes32 _instrumentId, bytes32 _investorId, bool _allowed, bytes32 _senderRole) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IBaseRegistry} from "src/interfaces/IBaseRegistry.sol";
import {IRoleRegistry} from "src/interfaces/IRoleRegistry.sol";
import {IInvestorRegistry} from "src/interfaces/IInvestorRegistry.sol";
import {IUserRegistry} from "src/interfaces/IUserRegistry.sol";
import {IOperationsEngine} from "src/interfaces/IOperationsEngine.sol";
import {IInstrumentRegistry} from "src/interfaces/IInstrumentRegistry.sol";
/**
* @title IDealerRegistry
* @notice Interface for managing dealers within the registry, including adding new dealers,
* allowing dealers for specific instruments, and checking dealer permissions.
* @dev Extends both `IBaseRegistry` and `IUserRegistry` for core registry and user management functionality.
*/
interface IDealerRegistry is IBaseRegistry, IUserRegistry {
/**
* @notice Thrown when attempting to add a dealer who is already registered.
*/
error IDealerRegistry_AlreadyADealer();
/**
* @notice Thrown when invalid input parameters are provided.
*/
error IDealerRegistry_InvalidInput();
/**
* @notice Thrown when the specified instrument does not exist in the registry.
*/
error IDealerRegistry_NonExistingInstrument();
/**
* @notice Thrown when the dealer is not allowed for the specified instrument.
*/
error IDealerRegistry_DealerNotAllowed();
/**
* @notice Emited when a new dealer is added
* @param dealerId Id of the new dealer
* @param wallet Initial wallet of the dealer
*/
event NewDealerAdded(bytes32 dealerId, address wallet);
/**
* @notice Emited when an dealer's allowed status is updated
* @param dealerId Id of the dealer updated
* @param allowed Y/N if dealer is allowed for the instrument
*/
event dealerAllowedUpdated(bytes32 dealerId, bytes32 instrumentId, bool allowed);
/**
* @notice Initialize the registry
* @param _roleRegistry Address of the role registry
*/
function initialize(
IRoleRegistry _roleRegistry,
IOperationsEngine _operationsEngine,
IInvestorRegistry _investorRegistry,
IInstrumentRegistry _instrumentRegistry
) external;
/**
* @notice Adds a new dealer to the registry
* @param _senderRole Role of the sender which allows the operation execution
* @param _dealerId ID of the dealer
* @param _wallet Wallet of the dealer
*/
function addDealer(bytes32 _senderRole, bytes32 _dealerId, address _wallet) external;
/**
* @notice Allows a dealer for a specific instrument
* @param _senderRole Role of the sender which allows the operation execution
* @param _dealerId ID of the dealer
* @param _instrumentId ID of the instrument
* @param _allowed Y/N if dealer is allowed for the instrument
*/
function allowDealer(bytes32 _senderRole, bytes32 _dealerId, bytes32 _instrumentId, bool _allowed) external;
/**
* @notice Returns if the dealer is allowed for a specific instrument
* @param _dealerId ID of the dealer
* @param _instrumentId ID of the instrument
* @return Bool indicating if dealer if allowed
*/
function isDealerAllowed(bytes32 _dealerId, bytes32 _instrumentId) external view returns (bool);
/**
* @notice Reverts if the dealer is not allowed for a specific instrument
* @param _dealerId ID of the dealer
* @param _instrumentId ID of the instrument
*/
function checkDealerAllowed(bytes32 _dealerId, bytes32 _instrumentId) external view;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IInvestorRegistry} from "src/interfaces/IInvestorRegistry.sol";
import {IFundRegistry} from "src/interfaces/IFundRegistry.sol";
import {IDealerRegistry} from "src/interfaces/IDealerRegistry.sol";
import {IInstrumentRegistry} from "src/interfaces/IInstrumentRegistry.sol";
import {IRoleRegistry} from "src/interfaces/IRoleRegistry.sol";
import {IEternalRegistryStorage} from "src/interfaces/IEternalRegistryStorage.sol";
import {OPERATIONS} from "./operations/IOperationModule.sol";
/**
* @title Operations Engine Interface
* @author Libre
* @notice Defines the interface for managing modules, operations, and dependencies in the system.
* @dev Includes error definitions, events, and function signatures for interacting with the operations engine.
*/
interface IOperationsEngine {
// Enums
/**
* @notice Defines the type of ID for the module check, modules are either tracking ones or check ones.
*/
enum IdType {
NULL,
INSTRUMENT_CHECK,
FEE,
TRACKING
}
/**
* @notice Defines the type of check a module performs.
*/
enum CHECK_TYPE {
BOOLEAN,
NUMERIC_MIN,
NUMERIC_MAX
}
// Errors
/**
* @dev Revert when the tracking module reverts for any reason
*/
error IOperationsEngine_TrackingModuleFailure();
/**
* @dev Revert when the fee module reverts for any reason
*/
error IOperationsEngine_FeeModuleFailure();
/**
* @dev Revert when the module address provided is invalid.
*/
error IOperationsEngine_InvalidModuleAddress();
/**
* @dev Revert when the module is not of the Libre type.
*/
error IOperationsEngine_ModuleIsNotLibreType();
/**
* @dev Revert when a lending module cannot be disabled.
*/
error IOperationsEngine_LendingModuleDisable();
/**
* @dev Revert when dependencies required for an operation are missing.
*/
error IOperationsEngine_MissingDependencies();
/**
* @dev Revert when an invalid check type is used.
*/
error IOperationsEngine_InvalidCheckType();
/**
* @dev Revert when the caller is not authorized to perform the action.
*/
error IOperationsEngine_CallerNotAuthorized();
/**
* @dev Revert when adding a module that is already been added.
*/
error IOperationsEngine_ModuleAlreadyAdded();
/**
* @dev Revert when module already enabled for the same instrument.
*/
error IOperationsEngine_ModuleAlreadyEnabled();
/**
* @dev Revert when a module to be disabled for an instrument is not enabled
*/
error IOperationsEngine_ModuleNotEnabled();
// Events
/**
* @notice Emitted when a module is added to the available modules library.
* @param moduleAddress Address of the module that was added.
*/
event ModuleAdded(address indexed moduleAddress);
/**
* @notice Emitted when a module is removed from the available modules library.
* @param moduleAddress Address of the module that was removed.
*/
event ModuleRemoved(address indexed moduleAddress);
/**
* @notice Emitted when a module is enabled for a specific instrument.
* @param moduleAddress Address of the module that was enabled.
* @param instrumentId Id of the instrument for which the module was enabled.
*/
event ModuleEnabled(address indexed moduleAddress, bytes32 instrumentId);
/**
* @notice Emitted when a module is disabled for a specific instrument.
* @param moduleAddress Address of the module that was disabled.
* @param instrumentId Id of the instrument for which the module was disabled.
*/
event ModuleDisabled(address indexed moduleAddress, bytes32 instrumentId);
/**
* @dev Event emitted when a fee is applied.
* @param instrumentId The ID of the instrument.
* @param orderId The ID of the order.
* @param feeModule The address of the fee module.
* @param feeAmount The amount of the fee applied.
*/
event FeeApplied(bytes32 indexed instrumentId, uint256 orderId, address feeModule, uint256 feeAmount);
//functions
/**
* @notice Initializes the Rules Engine with necessary registries.
* @param _investorRegistry Address of the Investor Registry.
* @param _dealerRegistry Address of the Dealer Registry.
* @param _fundRegistry Address of the Fund Registry.
* @param _instrumentRegistry Address of the Instrument Registry.
* @param _roleRegistry Address of the Role Registry.
* @param _jurisdictionRegistry Address of the Jurisdiction Registry.
*/
function initialize(
IInvestorRegistry _investorRegistry,
IDealerRegistry _dealerRegistry,
IFundRegistry _fundRegistry,
IInstrumentRegistry _instrumentRegistry,
IRoleRegistry _roleRegistry,
IEternalRegistryStorage _jurisdictionRegistry
) external;
/**
* @notice Gets the addresses for registered check modules implementing the given operation.
* @param _id Id of the dealer or instrument the modules belong to.
* @param _operation Operation implemented in modules.
* @return An array of addresses of modules implementing the given operation.
*/
function getCheckModules(bytes32 _id, OPERATIONS _operation) external view returns (address[] memory);
/**
* @notice Gets the addresses for registered fee modules implementing the given operation.
* @param _id Id of the dealer or instrument the modules belong to.
* @param _operation Operation implemented in modules.
* @return An array of addresses of modules implementing the given operation.
*/
function getFeeModules(bytes32 _id, OPERATIONS _operation) external view returns (address[] memory);
/**
* @notice Gets the addresses for registered tracking modules implementing the given operation.
* @param _id Id of the dealer or instrument the modules belong to.
* @param _operation Operation implemented in modules.
* @return An array of addresses of modules implementing the given operation.
*/
function getTrackingModules(bytes32 _id, OPERATIONS _operation) external view returns (address[] memory);
/**
* @notice Adds a module to the available modules library.
* @param _moduleAddress Address of the module to add.
* @param _role Role required to add the module.
* @param _idType Type of the module.
*/
function addModule(address _moduleAddress, bytes32 _role, IdType _idType) external;
/**
* @notice Removes a module from the available modules library.
* @param _moduleAddress Address of the module to remove.
* @param _role Role required to remove the module.
*/
function removeModule(address _moduleAddress, bytes32 _role) external;
/**
* @notice Enables a module for a specific instrument.
* @param _moduleAddress Address of the module to enable.
* @param _instrumentId Id of the instrument.
* @param _role Role required to enable the module.
*/
function enableModule(address _moduleAddress, bytes32 _instrumentId, bytes32 _role) external;
/**
* @notice Disables a module for a specific instrument.
* @param _moduleAddress Address of the module to disable.
* @param _instrumentId Id of the instrument.
* @param _role Role required to disable the module.
* @dev Lending modules cannot be disabled, because at least one module must be enabled at all times.
* Instead, the lending module can be replaced with another lending module by enabling the new module.
*/
function disableModule(address _moduleAddress, bytes32 _instrumentId, bytes32 _role) external;
/**
* @notice Checks if a module is available in the available modules library.
* @param _moduleAddress Address of the module to check.
* @return True if the module is available, false otherwise.
*/
function isAvailableModule(address _moduleAddress) external view returns (bool);
/**
* @notice Checks if a module is enabled for a specific instrument.
* @param _id Id of the instrument.
* @param _moduleName Hash of the abi.encodePacked of the module name
* @return True if the module is enabled, false otherwise.
*/
function hasModuleEnabled(bytes32 _id, bytes32 _moduleName) external view returns (bool);
/**
* @notice Function to be delegatecalled by the registry to perform the check
* @param _operation The operation to be checked
* @param _id The id of the operation
* @param _data Arbitrary data that can be used by the module to perform the check
* @return result memory Result of the check
*/
function check(OPERATIONS _operation, bytes32 _id, bytes calldata _data) external returns (bytes memory result);
/**
* @notice Tracks the operation
* @param _operation The operation to track
* @param _id The id of the instrument or investor
* @param _data The data to track
* @return True if the tracking was successful, false otherwise
*/
function track(OPERATIONS _operation, bytes32 _id, bytes memory _data) external returns (bool);
/**
* @notice Calculates the total fee amount to be deducted for a given operation and instrument.
* @dev Loops through all enabled fee modules for the given operation and instrument, calls them with the input data,
* and sums up the returned fee amounts. Also emits `FeeApplied` events for each individual module fee.
*
* @param _operation The operation type (e.g., SETTLE_SUBSCRIPTION_PER_ORDER).
* @param _id The instrument ID for which the fees are being calculated.
* @param _data ABI-encoded parameters required for fee calculation. Must encode the following values in order:
* - `uint256 _orderId`: Unique identifier of the order
* - `bytes32 _investorId`: The ID of the investor associated with the order
* - `uint256 _amountToSettle`: The current amount to be settled
*
* @return totalFee The total fee amount to be deducted across all enabled fee modules.
*/
function calculateFees(OPERATIONS _operation, bytes32 _id, bytes memory _data) external returns (uint256 totalFee);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
/**
* @title IUserRegistry
* @author Libre
* @notice Interface for managing user wallets and their association with investor/dealer IDs.
* @dev Provides functions for adding wallets, retrieving wallets, and mapping wallets to user IDs.
*/
interface IUserRegistry {
/**
* @notice Thrown when the wallet address being added is already associated with another user ID.
*/
error IUserRegistry_WalletAlreadyClaimed();
/**
* @notice Thrown when the provided signature fails to verify ownership of the wallet address.
*/
error IUserRegistry_WalletOwnershipVerificationFailure();
/**
* @notice Thrown when the provided wallet signature has expired.
*/
error IUserRegistry_WalletSignatureExpired();
/**
* @notice Thrown when the provided wallet address to add is blacklisted.
*/
error IUserRegistry_WalletBlacklisted();
/**
* @notice Emited when secondary wallet is removed
* @param wallet User wallet address
*/
event WalletAdded(address indexed wallet);
/**
* @notice Emited when secondary wallet is removed
* @param wallet User wallet address
*/
event WalletRemoved(address indexed wallet);
/**
* @notice Adds a new investor to the registry
* @param _userId The ID of the user.
* @param _wallet The wallet address to associate with the user ID.
* @param _role The role used by the caller.
*/
function addWallet(bytes32 _userId, address _wallet, bytes32 _role) external;
/**
* @notice Removes a wallet from the registry
* @param _wallet The wallet address to remove.
* @param _role The role used by the caller.
* @return The user ID that the wallet was removed from
*/
function removeWallet(address _wallet, bytes32 _role) external returns (bytes32);
/**
* @notice Get Investor/Dealer array of wallets
* @param _userId Investor/Dealer ID
*/
function getWallets(bytes32 _userId) external view returns (address[] memory);
/**
* @notice Get Investor/Dealer ID
* @param _wallet Investor/Dealer address
*/
function getIdFromWallet(address _wallet) external view returns (bytes32);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IInvestorRegistry} from "src/interfaces/IInvestorRegistry.sol";
import {IRoleRegistry} from "src/interfaces/IRoleRegistry.sol";
import {ILibreCoreGateway} from "src/interfaces/ILibreCoreGateway.sol";
import {IEAS} from "eas-contracts/IEAS.sol";
/**
* @title IGatewayManager Interface
* @notice Interface for managing cross-chain addresses and investor chain preferences
* @dev Coordinates with LibreCoreGateway for cross-chain operations
*/
interface IGatewayManager {
/**
* @notice Emitted when an investor's preferred chains are updated or set
* @param investorId The unique identifier of the investor
* @param chains Array of custom chain IDs that the investor prefers
* @param oldChains Previous array of chain IDs for the investor
*/
event InvestorChainsUpdated(bytes32 investorId, uint16[] chains, uint16[] oldChains);
/**
* @notice Emitted when cross-chain addresses are updated for an investor
* @dev Each address change is encoded as: [1 byte action][2 bytes chainSelector][n bytes address]
* @param investorId The unique identifier of the investor
* @param addressChanges A list of concatenated bytes describing a change in multi-chain address
*/
event InvestorAddressesUpdated(bytes32 investorId, bytes[] addressChanges);
/// @notice Thrown when an unsupported or invalid chain ID is provided
error GatewayManager_InvalidChain();
/// @notice Thrown when the investor ID doesn't exist or is invalid
error GatewayManager_InvalidInvestor();
/// @notice Thrown when input parameters are invalid or missing
error GatewayManager_InvalidInput();
/// @notice Thrown when a cross-chain address is already associated with another investor
error GatewayManager_AddressAlreadyUsed();
/**
* @notice Initializes the gateway manager
* @param _coreGateway Address of the LibreCoreGateway contract
* @param _eas Address of the Ethereum Attestation Service
* @param _investorRegistry Address of the InvestorRegistry contract
* @param _roleRegistry Address of the RoleRegistry contract
*/
function initialize(
ILibreCoreGateway _coreGateway,
IEAS _eas,
IInvestorRegistry _investorRegistry,
IRoleRegistry _roleRegistry
) external;
/**
* @notice Sets the preferred chains for an investor
* @param _senderRole Role of the transaction sender
* @param _investorId Unique identifier of the investor
* @param _chains Array of chain IDs to set as preferred
*/
function setInvestorChains(bytes32 _senderRole, bytes32 _investorId, uint16[] calldata _chains) external;
/**
* @notice Updates investor's cross-chain addresses and propagates changes to other chains
* @dev Adds or removes addresses and bridges the updates to other chains
* @param _senderRole Role of the transaction sender
* @param _investorId Unique identifier of the investor
* @param _addressChanges A list of concatenated bytes describing a change in multi-chain address
*/
function manageCrossChainAddresses(bytes32 _senderRole, bytes32 _investorId, bytes[] calldata _addressChanges)
external;
/**
* @notice Bridges a credential to all investor's preferred chains via core gateway.
* @param _attestationId The unique ID of the attestation to be bridged.
* @param _senderRole Role of the transaction sender.
* @param _chains Chains to bridge credential to (all investor chains if empty)
*/
function bridgeCredential(bytes32 _attestationId, bytes32 _senderRole, uint16[] memory _chains) external;
/**
* @notice Validates if an address is a valid cross-chain address for an investor
* @param _investorId The investor ID to check
* @param _chainSelector The chain ID to check
* @param _address The address to validate
* @return bool True if the address is valid for the investor on the chain
*/
function isValidCrossChainAddress(bytes32 _investorId, uint16 _chainSelector, bytes calldata _address)
external
view
returns (bool);
/**
* @notice Gets an investor's preferred chains
* @param _investorId The investor's unique identifier
* @return uint16[] Array of preferred chain IDs
*/
function getInvestorChains(bytes32 _investorId) external view returns (uint16[] memory);
/**
* @notice Gets the owner of a cross-chain address
* @param _chainSelector The chain ID of the address
* @param _address The address to get the owner of
* @return bytes32 The owner of the address
*/
function getAddressOwner(uint16 _chainSelector, bytes calldata _address) external view returns (bytes32);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
/**
* @title IEternalRegistryStorage
* @notice Interface for managing a flexible and extensible storage system, allowing various types of values to be
* stored and retrieved for specific registry entries. Provides a robust and modular way to interact with registry data.
* @dev Enables storage and retrieval of multiple data types (e.g., uint256, address, string, bool, bytes32) and
* supports operations like batch updates, array manipulations, and role-based access control for data modifications.
*/
interface IEternalRegistryStorage {
/**
* @notice Thrown when attempting to modify a key that has been restricted.
*/
error IEternalRegistryStorage_AttemptToSetARestrictedKey();
/**
* @notice Thrown when the length of the provided input arrays does not match.
*/
error IEternalRegistryStorage_BatchLengthMismatch();
/**
* @notice Thrown when attempting to access an array index that is out of bounds.
*/
error IEternalRegistryStorage_IndexShouldBeLessThanLengthOfTheArray();
/**
* @notice Emitted when a boolean value is added to the registry.
* @param id The identifier of the registry entry.
* @param key The key associated with the boolean value.
* @param value The boolean value added to the registry.
*/
event AddedBool(bytes32 indexed id, bytes32 indexed key, bool value);
/**
* @notice Emitted when a uint256 value is added to the registry.
* @param id The identifier of the registry entry.
* @param key The key associated with the uint256 value.
* @param value The uint256 value added to the registry.
*/
event AddedUint(bytes32 indexed id, bytes32 indexed key, uint256 value);
/**
* @notice Emitted when an address value is added to the registry.
* @param id The identifier of the registry entry.
* @param key The key associated with the address value.
* @param value The address value added to the registry.
*/
event AddedAddress(bytes32 indexed id, bytes32 indexed key, address value);
/**
* @notice Emitted when a string value is added to the registry.
* @param id The identifier of the registry entry.
* @param key The key associated with the string value.
* @param value The string value added to the registry.
*/
event AddedString(bytes32 indexed id, bytes32 indexed key, string value);
/**
* @notice Emitted when a bytes32 value is added to the registry.
* @param id The identifier of the registry entry.
* @param key The key associated with the bytes32 value.
* @param value The bytes32 value added to the registry.
*/
event AddedBytes(bytes32 indexed id, bytes32 indexed key, bytes32 value);
/**
* @notice Emitted every time a key is restricted from being set
* for an specific entry
* @param _id Id of the entry where the key is restricted
* @param _key Key being restricted
*/
event KeyRestricted(bytes32 indexed _id, bytes32 indexed _key);
/**
* @notice Get a boolean value from the storage
* @param _id Id of the registry entry to get the value from
* @param _key Key identifying the value to get
* @return bool value of the element associated to the key
* in the requested registry entry
*/
function getBool(bytes32 _id, bytes32 _key) external view returns (bool);
/**
* @notice Get a uint256 value from the storage
* @param _id Id of the registry entry to get the value from
* @param _key Key identifying the value to get
* @return uint256 value of the element associated to the key
* in the requested registry entry
*/
function getUint(bytes32 _id, bytes32 _key) external view returns (uint256);
/**
* @notice Get an address value from the storage
* @param _id Id of the registry entry to get the value from
* @param _key Key identifying the value to get
* @return address value of the element associated to the key
* in the requested registry entry
*/
function getAddress(bytes32 _id, bytes32 _key) external view returns (address);
/**
* @notice Get a string value from the storage
* @param _id Id of the registry entry to get the value from
* @param _key Key identifying the value to get
* @return string value of the element associated to the key
* in the requested registry entry
*/
function getString(bytes32 _id, bytes32 _key) external view returns (string memory);
/**
* @notice Get a bytes value from the storage
* @param _id Id of the registry entry to get the value from
* @param _key Key identifying the value to get
* @return bytes value of the element associated to the key
* in the requested registry entry
*/
function getBytes(bytes32 _id, bytes32 _key) external view returns (bytes32);
/**
* @notice Set a boolean value on the storage
* @param _id Id of the registry entry to set the value on
* @param _key Key identifying the value to set
* @param _value Value to set
* @param _senderRole Role of the sender allowing the operation
*/
function setBool(bytes32 _id, bytes32 _key, bool _value, bytes32 _senderRole) external;
/**
* @notice Set a uint256 value on the storage
* @param _id Id of the registry entry to set the value on
* @param _key Key identifying the value to set
* @param _value Value to set
* @param _senderRole Role of the sender allowing the operation
*/
function setUint(bytes32 _id, bytes32 _key, uint256 _value, bytes32 _senderRole) external;
/**
* @notice Set an address value on the storage
* @param _id Id of the registry entry to set the value on
* @param _key Key identifying the value to set
* @param _value Value to set
* @param _senderRole Role of the sender allowing the operation
*/
function setAddress(bytes32 _id, bytes32 _key, address _value, bytes32 _senderRole) external;
/**
* @notice Set a string value on the storage
* @param _id Id of the registry entry to set the value on
* @param _key Key identifying the value to set
* @param _value Value to set
* @param _senderRole Role of the sender allowing the operation
*/
function setString(bytes32 _id, bytes32 _key, string calldata _value, bytes32 _senderRole) external;
/**
* @notice Set a bytes value on the storage
* @param _id Id of the registry entry to set the value on
* @param _key Key identifying the value to set
* @param _value Value to set
* @param _senderRole Role of the sender allowing the operation
*/
function setBytes(bytes32 _id, bytes32 _key, bytes32 _value, bytes32 _senderRole) external;
/**
* @notice Set multiple values in one transaction
* @param _ids Ids associated to the values to set
* @param _keys Key associated to the values to set
* @param _boolValues Bool values to set
* @param _uintValues Uint256 values to set
* @param _addressValues Address values to set
* @param _stringValues String values to set
* @param _bytesValues Bytes32 values to set
* @param _senderRole Role of the sender allowing the operation
*/
function setBatch(
bytes32[] memory _ids,
bytes32[] memory _keys,
bool[] memory _boolValues,
uint256[] memory _uintValues,
address[] memory _addressValues,
string[] memory _stringValues,
bytes32[] memory _bytesValues,
bytes32 _senderRole
) external;
/**
* @notice Get multiple values in one transaction
* @param _ids Ids associated to the values to get
* @param _keys Keys associated to the values to get
* @param _boolCount Number of bool values to get
* @param _uintCount Number of uint256 values to get
* @param _addressCount Number of address values to get
* @param _stringCount Number of string values to get
* @param _bytesCount Number of bytes32 values to get
* @return _boolValues Bool values return array
* @return _uintValues Uint256 values return array
* @return _addressValues Address values return array
* @return _stringValues String values return array
* @return _bytesValues Bytes32 values return array
*/
function getBatch(
bytes32[] memory _ids,
bytes32[] memory _keys,
uint256 _boolCount,
uint256 _uintCount,
uint256 _addressCount,
uint256 _stringCount,
uint256 _bytesCount
)
external
view
returns (
bool[] memory _boolValues,
uint256[] memory _uintValues,
address[] memory _addressValues,
string[] memory _stringValues,
bytes32[] memory _bytesValues
);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
// @notice The mapping of whitelisted instruments with expirations
struct InstrumentAccess {
//Id of the investor
bytes32 investorId;
//Credential expiry timestamp
uint64 expiryTimestamp;
//Ids of instruments the investor is registered for
bytes32[] instrumentIds;
//Access expiry timestamps for instruments the investor is registered for
uint64[] instrumentExpiryTimestamps;
}// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; //The encodings used for jurisdictions are based and ordered after the ISO 3166 standard as of 2023/11/28 //(https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) //Any new additions after this date will be added at the end as to not modify existing encodings //allowed values are in the range of: 2^x, 0 ≤ x ≤ 255 uint256 constant AF = 2 ** 0; uint256 constant AX = 2 ** 1; uint256 constant AL = 2 ** 2; uint256 constant DZ = 2 ** 3; uint256 constant AS = 2 ** 4; uint256 constant AD = 2 ** 5; uint256 constant AO = 2 ** 6; uint256 constant AI = 2 ** 7; uint256 constant AQ = 2 ** 8; uint256 constant AG = 2 ** 9; uint256 constant AR = 2 ** 10; uint256 constant AM = 2 ** 11; uint256 constant AW = 2 ** 12; uint256 constant AU = 2 ** 13; uint256 constant AT = 2 ** 14; uint256 constant AZ = 2 ** 15; uint256 constant BS = 2 ** 16; uint256 constant BH = 2 ** 17; uint256 constant BD = 2 ** 18; uint256 constant BB = 2 ** 19; uint256 constant BY = 2 ** 20; uint256 constant BE = 2 ** 21; uint256 constant BZ = 2 ** 22; uint256 constant BJ = 2 ** 23; uint256 constant BM = 2 ** 24; uint256 constant BT = 2 ** 25; uint256 constant BO = 2 ** 26; uint256 constant BQ = 2 ** 27; uint256 constant BA = 2 ** 28; uint256 constant BW = 2 ** 29; uint256 constant BV = 2 ** 30; uint256 constant BR = 2 ** 31; uint256 constant IO = 2 ** 32; uint256 constant BN = 2 ** 33; uint256 constant BG = 2 ** 34; uint256 constant BF = 2 ** 35; uint256 constant BI = 2 ** 36; uint256 constant CV = 2 ** 37; uint256 constant KH = 2 ** 38; uint256 constant CM = 2 ** 39; uint256 constant CA = 2 ** 40; uint256 constant KY = 2 ** 41; uint256 constant CF = 2 ** 42; uint256 constant TD = 2 ** 43; uint256 constant CL = 2 ** 44; uint256 constant CN = 2 ** 45; uint256 constant CX = 2 ** 46; uint256 constant CC = 2 ** 47; uint256 constant CO = 2 ** 48; uint256 constant KM = 2 ** 49; uint256 constant CD = 2 ** 50; uint256 constant CG = 2 ** 51; uint256 constant CK = 2 ** 52; uint256 constant CR = 2 ** 53; uint256 constant CI = 2 ** 54; uint256 constant HR = 2 ** 55; uint256 constant CU = 2 ** 56; uint256 constant CW = 2 ** 57; uint256 constant CY = 2 ** 58; uint256 constant CZ = 2 ** 59; uint256 constant DK = 2 ** 60; uint256 constant DJ = 2 ** 61; uint256 constant DM = 2 ** 62; uint256 constant DO = 2 ** 63; uint256 constant EC = 2 ** 64; uint256 constant EG = 2 ** 65; uint256 constant SV = 2 ** 66; uint256 constant GQ = 2 ** 67; uint256 constant ER = 2 ** 68; uint256 constant EE = 2 ** 69; uint256 constant SZ = 2 ** 70; uint256 constant ET = 2 ** 71; uint256 constant FK = 2 ** 72; uint256 constant FO = 2 ** 73; uint256 constant FJ = 2 ** 74; uint256 constant FI = 2 ** 75; uint256 constant FR = 2 ** 76; uint256 constant GF = 2 ** 77; uint256 constant PF = 2 ** 78; uint256 constant TF = 2 ** 79; uint256 constant GA = 2 ** 80; uint256 constant GM = 2 ** 81; uint256 constant GE = 2 ** 82; uint256 constant DE = 2 ** 83; uint256 constant GH = 2 ** 84; uint256 constant GI = 2 ** 85; uint256 constant GR = 2 ** 86; uint256 constant GL = 2 ** 87; uint256 constant GD = 2 ** 88; uint256 constant GP = 2 ** 89; uint256 constant GU = 2 ** 90; uint256 constant GT = 2 ** 91; uint256 constant GG = 2 ** 92; uint256 constant GN = 2 ** 93; uint256 constant GW = 2 ** 94; uint256 constant GY = 2 ** 95; uint256 constant HT = 2 ** 96; uint256 constant HM = 2 ** 97; uint256 constant VA = 2 ** 98; uint256 constant HN = 2 ** 99; uint256 constant HK = 2 ** 100; uint256 constant HU = 2 ** 101; uint256 constant IS = 2 ** 102; uint256 constant IN = 2 ** 103; uint256 constant ID = 2 ** 104; uint256 constant IR = 2 ** 105; uint256 constant IQ = 2 ** 106; uint256 constant IE = 2 ** 107; uint256 constant IM = 2 ** 108; uint256 constant IL = 2 ** 109; uint256 constant IT = 2 ** 110; uint256 constant JM = 2 ** 111; uint256 constant JP = 2 ** 112; uint256 constant JE = 2 ** 113; uint256 constant JO = 2 ** 114; uint256 constant KZ = 2 ** 115; uint256 constant KE = 2 ** 116; uint256 constant KI = 2 ** 117; uint256 constant KP = 2 ** 118; uint256 constant KR = 2 ** 119; uint256 constant KW = 2 ** 120; uint256 constant KG = 2 ** 121; uint256 constant LA = 2 ** 122; uint256 constant LV = 2 ** 123; uint256 constant LB = 2 ** 124; uint256 constant LS = 2 ** 125; uint256 constant LR = 2 ** 126; uint256 constant LY = 2 ** 127; uint256 constant LI = 2 ** 128; uint256 constant LT = 2 ** 129; uint256 constant LU = 2 ** 130; uint256 constant MO = 2 ** 131; uint256 constant MK = 2 ** 132; uint256 constant MG = 2 ** 133; uint256 constant MW = 2 ** 134; uint256 constant MY = 2 ** 135; uint256 constant MV = 2 ** 136; uint256 constant ML = 2 ** 137; uint256 constant MT = 2 ** 138; uint256 constant MH = 2 ** 139; uint256 constant MQ = 2 ** 140; uint256 constant MR = 2 ** 141; uint256 constant MU = 2 ** 142; uint256 constant YT = 2 ** 143; uint256 constant MX = 2 ** 144; uint256 constant FM = 2 ** 145; uint256 constant MD = 2 ** 146; uint256 constant MC = 2 ** 147; uint256 constant MN = 2 ** 148; uint256 constant ME = 2 ** 149; uint256 constant MS = 2 ** 150; uint256 constant MA = 2 ** 151; uint256 constant MZ = 2 ** 152; uint256 constant MM = 2 ** 153; uint256 constant NA = 2 ** 154; uint256 constant NR = 2 ** 155; uint256 constant NP = 2 ** 156; uint256 constant NL = 2 ** 157; uint256 constant NC = 2 ** 158; uint256 constant NZ = 2 ** 159; uint256 constant NI = 2 ** 160; uint256 constant NE = 2 ** 161; uint256 constant NG = 2 ** 162; uint256 constant NU = 2 ** 163; uint256 constant NF = 2 ** 164; uint256 constant MP = 2 ** 165; uint256 constant NO = 2 ** 166; uint256 constant OM = 2 ** 167; uint256 constant PK = 2 ** 168; uint256 constant PW = 2 ** 169; uint256 constant PS = 2 ** 170; uint256 constant PA = 2 ** 171; uint256 constant PG = 2 ** 172; uint256 constant PY = 2 ** 173; uint256 constant PE = 2 ** 174; uint256 constant PH = 2 ** 175; uint256 constant PN = 2 ** 176; uint256 constant PL = 2 ** 177; uint256 constant PT = 2 ** 178; uint256 constant PR = 2 ** 179; uint256 constant QA = 2 ** 180; uint256 constant RE = 2 ** 181; uint256 constant RO = 2 ** 182; uint256 constant RU = 2 ** 183; uint256 constant RW = 2 ** 184; uint256 constant BL = 2 ** 185; uint256 constant SH = 2 ** 186; uint256 constant KN = 2 ** 187; uint256 constant LC = 2 ** 188; uint256 constant MF = 2 ** 189; uint256 constant PM = 2 ** 190; uint256 constant VC = 2 ** 191; uint256 constant WS = 2 ** 192; uint256 constant SM = 2 ** 193; uint256 constant ST = 2 ** 194; uint256 constant SA = 2 ** 195; uint256 constant SN = 2 ** 196; uint256 constant RS = 2 ** 197; uint256 constant SC = 2 ** 198; uint256 constant SL = 2 ** 199; uint256 constant SG = 2 ** 200; uint256 constant SX = 2 ** 201; uint256 constant SK = 2 ** 202; uint256 constant SI = 2 ** 203; uint256 constant SB = 2 ** 204; uint256 constant SO = 2 ** 205; uint256 constant ZA = 2 ** 206; uint256 constant GS = 2 ** 207; uint256 constant SS = 2 ** 208; uint256 constant ES = 2 ** 209; uint256 constant LK = 2 ** 210; uint256 constant SD = 2 ** 211; uint256 constant SR = 2 ** 212; uint256 constant SJ = 2 ** 213; uint256 constant SE = 2 ** 214; uint256 constant CH = 2 ** 215; uint256 constant SY = 2 ** 216; uint256 constant TW = 2 ** 217; uint256 constant TJ = 2 ** 218; uint256 constant TZ = 2 ** 219; uint256 constant TH = 2 ** 220; uint256 constant TL = 2 ** 221; uint256 constant TG = 2 ** 222; uint256 constant TK = 2 ** 223; uint256 constant TO = 2 ** 224; uint256 constant TT = 2 ** 225; uint256 constant TN = 2 ** 226; uint256 constant TR = 2 ** 227; uint256 constant TM = 2 ** 228; uint256 constant TC = 2 ** 229; uint256 constant TV = 2 ** 230; uint256 constant UG = 2 ** 231; uint256 constant UA = 2 ** 232; uint256 constant AE = 2 ** 233; uint256 constant GB = 2 ** 234; uint256 constant UM = 2 ** 235; uint256 constant US = 2 ** 236; uint256 constant UY = 2 ** 237; uint256 constant UZ = 2 ** 238; uint256 constant VU = 2 ** 239; uint256 constant VE = 2 ** 240; uint256 constant VN = 2 ** 241; uint256 constant VG = 2 ** 242; uint256 constant VI = 2 ** 243; uint256 constant WF = 2 ** 244; uint256 constant EH = 2 ** 245; uint256 constant YE = 2 ** 246; uint256 constant ZM = 2 ** 247; uint256 constant ZW = 2 ** 248; //values 249-255 reserved for future additions
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.19;
import "./math/Math.sol";
import "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.19;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @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);
/**
* @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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.19;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControlUpgradeable {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.19;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IBaseRegistry} from "src/interfaces/IBaseRegistry.sol";
import {IRoleRegistry} from "src/interfaces/IRoleRegistry.sol";
import {IOperationsEngine} from "src/interfaces/IOperationsEngine.sol";
/**
* @title IFundRegistry
* @author Libre
* @notice Interface for managing and storing information related to funds within a registry.
* Provides functionality to initialize the registry, add new funds, and emit events for key actions.
*/
interface IFundRegistry is IBaseRegistry {
/// @notice Error raised when attempting to register a fund that is already registered.
error IFundRegistry_AlreadyRegistered();
/**
* @notice Emited when a new Fund is added
* @param fundId Id of the new fund
*/
event NewFundAdded(bytes32 indexed fundId);
/**
* @notice Initialize the registry
* @param _roleRegistry Address of the role registry
*/
function initialize(IRoleRegistry _roleRegistry, IOperationsEngine _operationsEngine) external;
/**
* @notice Adds a new fund to the registry
* @param _senderRole Role of the sender which allow the operation execution
* @param _fundId The ID of the fund
*/
function addNewFund(bytes32 _senderRole, bytes32 _fundId) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IInvestorRegistry} from "src/interfaces/IInvestorRegistry.sol";
import {IFundRegistry} from "src/interfaces/IFundRegistry.sol";
import {IDealerRegistry} from "src/interfaces/IDealerRegistry.sol";
import {IInstrumentRegistry} from "src/interfaces/IInstrumentRegistry.sol";
import {IEternalRegistryStorage} from "src/interfaces/IEternalRegistryStorage.sol";
import {IRoleRegistry} from "src/interfaces/IRoleRegistry.sol";
enum OPERATIONS {
// Transfer specific operations:
TRANSFER,
FORCED_TRANSFER,
RECEIVE,
SEND,
CLAWBACK,
// Subscription specific operations:
ADVISED_CREATE_SUBSCRIPTION,
CREATE_SUBSCRIPTION,
SUBSCRIPTION_EXECUTION_DATE_CALCULATION,
SETTLE_SUBSCRIPTIONS,
SETTLE_SUBSCRIPTION_PER_ORDER,
SUBSCRIPTION_CANCELLATION,
// Redemption specific operations:
ADVISED_CREATE_REDEMPTION,
CREATE_REDEMPTION,
REDEMPTION_EXECUTION_DATE_CALCULATION,
REDEMPTION_CANCELLATION,
SETTLE_REDEMPTIONS,
SETTLE_REDEMPTION_PER_ORDER,
FORCED_REDEMPTION,
REDEMPTION_FEE,
// Secondary Market specific operations:
FILL,
ORDER,
TRADE,
// NAV operations:
UPDATE_AUDITED_NAV_PER_SHARE
}
interface IOperationModule {
/**
* @return The list of operations associated with a module
* @dev It should contains all the Operation ids of all
* the IOperations it implements
*/
function getOperations() external pure returns (OPERATIONS[] memory);
/**
* @return Returns the name of the module
*/
function name() external pure returns (string memory);
/**
* @return Returns the hash of the module name
*/
function nameHash() external pure returns (bytes32);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IInvestorRegistry} from "src/interfaces/IInvestorRegistry.sol";
import {IInstrumentRegistry} from "src/interfaces/IInstrumentRegistry.sol";
import {IRoleRegistry} from "src/interfaces/IRoleRegistry.sol";
import {IGatewayManager} from "src/interfaces/IGatewayManager.sol";
import {Attestation} from "eas-contracts/IEAS.sol";
import {UidOp} from "src/lib/OperationId.sol";
/**
* @notice Structure representing token transfer details across chains
* @dev Used for both locking and unlocking operations
*/
struct TokenTransfer {
uint16 chainSelector; // Unique 16-bit Custom Chain ID where the Token is transfered
bytes32 instrumentId; // Instrument ID associated with the security token
bytes32 investorId; // Investor ID associated with the sender
bytes receiver; // Recipient's address for minting/unlocking
uint256 amount; // Amount of the asset to transfer
}
/**
* @notice Structure for managing investor addresses across specific chain
* @dev Each address change is encoded as: [1 byte action][n bytes address]
*/
struct ChainInvestorAddresses {
// Unique investor ID
bytes32 investorId;
// Unique chain ID
uint16 chainSelector;
// Address size for that chain
uint8 addressSize;
// A list of concatenated bytes describing a change in addresses
// Format `addressChanges`` := bytes1 action ++ bytes accountAddress
// where `action`: 0b0 -> Add, 0b1 -> Remove
bytes[] addressChanges;
}
/// @notice Interface for the Libre Core Gateway.
interface ILibreCoreGateway {
// Events
/**
* @notice Emitted when tokens are locked on source chain
* @param uid Unique identifier of the originating bridge operation
* @param encodedTransferDetails ABI-encoded TokenTransfer struct
*/
event TokenLockedAndBridged(bytes32 indexed uid, bytes encodedTransferDetails);
/**
* @notice Emitted when tokens are unlocked on destination chain
* @param uid Unique identifier of the originating bridge operation
* @param encodedTransferDetails ABI-encoded TokenTransfer struct
*/
event TokenUnlocked(bytes32 indexed uid, bytes encodedTransferDetails);
/**
* @notice Emitted when a credential is bridged to other chains
* @param investorId Investor ID of the investor
* @param chainSelectors Array of destination chains where credential is bridged
* @param uid Unique identifier of the originating bridge operation
*/
event CredentialBridged(bytes32 indexed investorId, uint16[] chainSelectors, bytes32 indexed uid);
/**
* @notice Emitted when investor chain-specific addresses are bridged
* @param uid Unique identifier of the originating bridge operation
* @param investorId Investor ID of the investor
* @param investorDestChainSelectors Array of destination chain selectors that investor has addresses on
* @param encodedChainInvestorAddresses ABI-encoded ChainInvestorAddresses struct
*/
event ChainInvestorAddressesBridged(
bytes32 indexed uid,
bytes32 investorId,
uint16[] investorDestChainSelectors,
bytes encodedChainInvestorAddresses
);
/**
* @notice Emitted when chain support status is updated
* @param chainSelector Chain ID whose support status changed
* @param isSupported New support status
*/
event ChainSupportUpdated(uint16 chainSelector, bool isSupported);
/**
* @notice Emitted when chain variable length address support status is updated
* @param _chainSelector Chain ID whose support status changed
* @param _isVariableLengthAddress New support status
*/
event ChainVariableLengthAddressSupportUpdated(uint16 _chainSelector, bool _isVariableLengthAddress);
// Custom Errors
/// @notice Thrown when operation is attempted on an unsupported chain
/// @param chainSelector The unsupported chain ID
error CoreGateway_ChainNotSupported(uint16 chainSelector);
/// @notice Thrown when the chain selector (chain ID) not matches with Native chain ID for unlock requests
error CoreGateway_InvalidNativeChainSelector();
/// @notice Thrown when token address is not found or invalid
/// @param token The invalid token address
error CoreGateway_TokenAddressNotFound(address token);
/// @notice Thrown when attempting transfer with zero amount
error CoreGateway_ZeroAmount();
/// @notice Thrown when transfer validation fails
error CoreGateway_InvalidTransfer();
/// @notice Thrown when provided investor id is not found
error CoreGateway_InvalidInvestor();
/// @notice Thrown when wrong inputs are provided
error CoreGateway_InvalidInput();
/// @notice Thrown when credential to be bridged are not stored or mismatches with registry
error CoreGateway_InvalidCredential();
/// @notice Thrown when an attempted status update results in no actual change.
error CoreGateway_NoStatusChanged();
/// @notice Thrown when trying to use a UID that has already been used for a different operation
error CoreGateway_UidAlreadyUsed();
/// @notice Thrown when the UID operation state is invalid for the current operation
error CoreGateway_InvalidUidOperation();
/// @notice Thrown when trying to set operation to Unset
error CoreGateway_CannotSetUnsetOperation();
/// @notice Thrown when credential has already been bridged to a specific chain
/// @param chainSelector The chain that already has this credential
error CoreGateway_CredentialAlreadyBridged(uint16 chainSelector);
/**
* @notice Initializes the gateway contract
* @param _instrumentRegistry Address of the Instrument Registry
* @param _investorRegistry Address of the Investor Registry
* @param _gatewayManager Address of the Gateway Manager
* @param _roleRegistry Address of the Role Registry
* @param _supportedChains Array of supported custom chain Ids
*/
function initialize(
IInstrumentRegistry _instrumentRegistry,
IInvestorRegistry _investorRegistry,
IGatewayManager _gatewayManager,
IRoleRegistry _roleRegistry,
uint16[] memory _supportedChains
) external;
/**
* @notice Locks tokens for cross-chain transfer and emits event for minting
* @dev Validates investor credentials and cross-chain addresses before locking
* @param transferDetails The details of the token transfer.
*/
function lockAndBridge(TokenTransfer calldata transferDetails) external;
/**
* @notice Unlocks tokens on the source chain
* @dev Called by bridge operators to release tokens to the recipient
* @param _senderRole The role of the caller
* @param encodedTransferDetails ABI-encoded transfer details
* @param uid Unique identifier of the originating bridge operation
*/
function unlock(bytes32 _senderRole, bytes calldata encodedTransferDetails, bytes32 uid) external;
/**
* @notice Bridges a credential to one or more destination chains.
* @dev Perform below steps:
* 1. Verifies all destination chains are supported
* 2. Validates the attestation matches the stored credential for the investor
* 3. Emits CredentialBridged event for cross-chain communication
* @param _senderRole The role of the caller
* @param attestation The attestation details to bridge.
* @param destinationChainSelectors Array of destination chain IDs.
*/
function bridgeCredential(
bytes32 _senderRole,
Attestation calldata attestation,
uint16[] calldata destinationChainSelectors
) external;
/**
* @notice Bridges investor addresses updates.
* @dev Processes and broadcasts chain specific address changes across destination chains
* Destination chains are extracted from _addressChanges to avoid parameter redundancy
* UID is generated internally and nonce is incremented for operation tracking
* Emits `ChainInvestorAddressesBridged` event for each chain's address updates.
*
* @param _senderRole The role of the caller for authorization
* @param _investorId The unique identifier of the investor whose addresses are being updated
* @param _addressChanges Array of encoded address changes containing chain and address information
* @param investorDestChainSelectors Array of destination chain selectors that investor has addresses on
*/
function bridgeInvestorAddresses(
bytes32 _senderRole,
bytes32 _investorId,
bytes[] calldata _addressChanges,
uint16[] calldata investorDestChainSelectors
) external;
/**
* @notice Pauses all gateway operations
* @param _senderRole The role of the caller
*/
function pause(bytes32 _senderRole) external;
/**
* @notice Unpauses gateway operations
* @param _senderRole The role of the caller
*/
function unpause(bytes32 _senderRole) external;
/**
* @notice Enables or disables support for a specific chain.
* @param _senderRole The role of the caller
* @param chainSelector The Custom chain ID.
* @param isSupported Whether the chain is supported.
*/
function setChainSupport(bytes32 _senderRole, uint16 chainSelector, bool isSupported) external;
/**
* @notice Enables or disables support for variable length addresses for a specific chain.
* @param _senderRole The role of the caller
* @param _chainSelector The Custom chain ID.
* @param _isVariableLengthAddress Whether variable length addresses for the chain are supported.
*/
function setChainVariableLengthAddressSupport(
bytes32 _senderRole,
uint16 _chainSelector,
bool _isVariableLengthAddress
) external;
/**
* @notice Retrieves the total amount of a specific instrument/token locked in the gateway.
* @param instrumentId The Instrument ID associated with the security token
* @return The total amount of the token locked in the gateway
*/
function getLockedBalance(bytes32 instrumentId) external view returns (uint256);
/**
* @notice Checks if a chain is supported.
* @param chainSelector The ID of the chain to check.
* @return True if the chain is supported, false otherwise.
*/
function isSupportedChain(uint16 chainSelector) external view returns (bool);
/**
* @notice Gets the list of supported chains
* @return uint16[] Array of supported chain IDs
*/
function getSupportedChains() external view returns (uint16[] memory);
/**
* @notice Gets the last operation performed with a specific UID.
* @param uid The unique identifier to query.
* @return The last operation performed with the given UID.
*/
function getUidLastOp(bytes32 uid) external view returns (UidOp);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.19;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v5.0._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v5.0._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v5.0._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v5.0._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v5.0._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.19;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.19;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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);
/**
* @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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
// Enum representing last operation with UID
enum UidOp {
Unset, // default value for unset entries
MintUnlock,
BurnLock,
CredentialSync,
AddressSync
}
/**
* @title OperationId
* @notice Library for generating unique identifiers for cross-chain operations
* @dev Used to create consistent UIDs across source and destination chains
*/
library OperationId {
/**
* @notice Generate a new unique id for the bridge operation
* @param _nonce Current operation nonce
* @param _sourceChainSelector Chain selector of the source chain
* @param _destChainSelector Chain selector of the destination chain
* @param _investorId Investor ID bytes
* @return bytes32 Unique operation identifier
*/
function generate(uint128 _nonce, uint16 _sourceChainSelector, uint16 _destChainSelector, bytes32 _investorId)
internal
pure
returns (bytes32)
{
return keccak256(abi.encodePacked(_nonce, _sourceChainSelector, _destChainSelector, _investorId));
}
}{
"remappings": [
"lib/aave-v3-horizon/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable:@openzeppelin/contracts-upgradeable/=lib/aave-v3-horizon/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/contracts/",
"lib/aave-v3-horizon/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable:@openzeppelin/contracts/=lib/aave-v3-horizon/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
"lib/aave-v3-horizon:solidity-utils/=lib/aave-v3-horizon/lib/solidity-utils/src/",
"lib/aave-v3-horizon:forge-std/=lib/aave-v3-horizon/lib/forge-std/src/",
"lib/aave-v3-horizon:ds-test/=lib/aave-v3-horizon/lib/forge-std/lib/ds-test/src/",
"lib/aave-v3-horizon:openzeppelin-contracts-upgradeable/=lib/aave-v3-horizon/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/",
"lib/aave-v3-horizon:openzeppelin-contracts/=lib/aave-v3-horizon/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/openzeppelin-contracts/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"eas-contracts/=lib/eas-contracts/contracts/",
"safe-contracts/=lib/safe-contracts/contracts/",
"@aave-v3-horizon/=lib/aave-v3-horizon/",
"BokkyPooBahsDateTimeLibrary/=lib/BokkyPooBahsDateTimeLibrary/",
"aave-v3-horizon/=lib/aave-v3-horizon/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"halmos-cheatcodes/=lib/aave-v3-horizon/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
"risc0-ethereum/=lib/risc0-ethereum/",
"solidity-utils/=lib/aave-v3-horizon/lib/solidity-utils/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IEAS","name":"eas","type":"address"},{"internalType":"contract IInvestorRegistry","name":"_investorRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessDenied","type":"error"},{"inputs":[],"name":"InsufficientValue","type":"error"},{"inputs":[],"name":"InvalidEAS","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[],"name":"NotPayable","type":"error"},{"inputs":[{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"bytes32","name":"schema","type":"bytes32"},{"internalType":"uint64","name":"time","type":"uint64"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"uint64","name":"revocationTime","type":"uint64"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Attestation","name":"attestation","type":"tuple"}],"name":"attest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"investorRegistry","outputs":[{"internalType":"contract IInvestorRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPayable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"bytes32","name":"schema","type":"bytes32"},{"internalType":"uint64","name":"time","type":"uint64"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"uint64","name":"revocationTime","type":"uint64"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Attestation[]","name":"attestations","type":"tuple[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"multiAttest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"bytes32","name":"schema","type":"bytes32"},{"internalType":"uint64","name":"time","type":"uint64"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"uint64","name":"revocationTime","type":"uint64"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Attestation[]","name":"attestations","type":"tuple[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"multiRevoke","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"bytes32","name":"schema","type":"bytes32"},{"internalType":"uint64","name":"time","type":"uint64"},{"internalType":"uint64","name":"expirationTime","type":"uint64"},{"internalType":"uint64","name":"revocationTime","type":"uint64"},{"internalType":"bytes32","name":"refUID","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"attester","type":"address"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Attestation","name":"attestation","type":"tuple"}],"name":"revoke","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
610120604052348015610010575f5ffd5b50604051610b0e380380610b0e83398101604081905261002f91610095565b6001608052600360a0525f60c052816001600160a01b038116610065576040516341bc07ff60e11b815260040160405180910390fd5b6001600160a01b0390811660e0521661010052506100cd565b6001600160a01b0381168114610092575f5ffd5b50565b5f5f604083850312156100a6575f5ffd5b82516100b18161007e565b60208401519092506100c28161007e565b809150509250929050565b60805160a05160c05160e051610100516109fe6101105f395f818160a401526104a601525f61045b01525f6101cb01525f6101a201525f61017901526109fe5ff3fe608060405260043610610071575f3560e01c806391db0b7e1161004c57806391db0b7e14610127578063ce46e0461461013a578063e49617e11461014c578063e60c35051461015f575f5ffd5b80633734256e1461009357806354fd4d50146100e357806388e5b2d914610104575f5ffd5b3661008f57604051631574f9f360e01b815260040160405180910390fd5b5f5ffd5b34801561009e575f5ffd5b506100c67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100ee575f5ffd5b506100f7610172565b6040516100da9190610603565b610117610112366004610680565b610215565b60405190151581526020016100da565b610117610135366004610680565b6102e0565b348015610145575f5ffd5b505f610117565b61011761015a3660046106ec565b61039b565b61011761016d3660046106ec565b6103ad565b606061019d7f00000000000000000000000000000000000000000000000000000000000000006103c0565b6101c67f00000000000000000000000000000000000000000000000000000000000000006103c0565b6101ef7f00000000000000000000000000000000000000000000000000000000000000006103c0565b60405160200161020193929190610742565b604051602081830303815290604052905090565b5f61021e610450565b8382811461023f5760405163251f56a160e21b815260040160405180910390fd5b345f5b828110156102d0575f86868381811061025d5761025d610781565b905060200201359050828111156102875760405163044044a560e21b815260040160405180910390fd5b6102b489898481811061029c5761029c610781565b90506020028101906102ae9190610795565b50600190565b6102c4575f9450505050506102d8565b90910390600101610242565b506001925050505b949350505050565b5f6102e9610450565b8382811461030a5760405163251f56a160e21b815260040160405180910390fd5b345f5b828110156102d0575f86868381811061032857610328610781565b905060200201359050828111156103525760405163044044a560e21b815260040160405180910390fd5b61037f89898481811061036757610367610781565b90506020028101906103799190610795565b8261049b565b61038f575f9450505050506102d8565b9091039060010161030d565b5f6103a4610450565b60015b92915050565b5f6103b6610450565b6103a7823461049b565b60605f6103cc8361052c565b60010190505f8167ffffffffffffffff8111156103eb576103eb6107b4565b6040519080825280601f01601f191660200182016040528015610415576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461041f57509392505050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461049957604051634ca8886760e01b815260040160405180910390fd5b565b5f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166104d7610100850160e086016107c8565b6001600160a01b0316146104ec57505f6103a7565b5f806104fc6101208601866107ee565b8101906105099190610904565b92509250508051825114610521575f925050506103a7565b506001949350505050565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061056a5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310610596576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106105b457662386f26fc10000830492506010015b6305f5e10083106105cc576305f5e100830492506008015b61271083106105e057612710830492506004015b606483106105f2576064830492506002015b600a83106103a75760010192915050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f83601f840112610648575f5ffd5b50813567ffffffffffffffff81111561065f575f5ffd5b6020830191508360208260051b8501011115610679575f5ffd5b9250929050565b5f5f5f5f60408587031215610693575f5ffd5b843567ffffffffffffffff8111156106a9575f5ffd5b6106b587828801610638565b909550935050602085013567ffffffffffffffff8111156106d4575f5ffd5b6106e087828801610638565b95989497509550505050565b5f602082840312156106fc575f5ffd5b813567ffffffffffffffff811115610712575f5ffd5b82016101408185031215610724575f5ffd5b9392505050565b5f81518060208401855e5f93019283525090919050565b5f61074d828661072b565b601760f91b8152610761600182018661072b565b9050601760f91b8152610777600182018561072b565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f823561013e198336030181126107aa575f5ffd5b9190910192915050565b634e487b7160e01b5f52604160045260245ffd5b5f602082840312156107d8575f5ffd5b81356001600160a01b0381168114610724575f5ffd5b5f5f8335601e19843603018112610803575f5ffd5b83018035915067ffffffffffffffff82111561081d575f5ffd5b602001915036819003821315610679575f5ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561085a5761085a6107b4565b604052919050565b5f67ffffffffffffffff82111561087b5761087b6107b4565b5060051b60200190565b5f82601f830112610894575f5ffd5b81356108a76108a282610862565b610831565b8082825260208201915060208360051b8601019250858311156108c8575f5ffd5b602085015b838110156108fa57803567ffffffffffffffff811681146108ec575f5ffd5b8352602092830192016108cd565b5095945050505050565b5f5f5f60608486031215610916575f5ffd5b83359250602084013567ffffffffffffffff811115610933575f5ffd5b8401601f81018613610943575f5ffd5b80356109516108a282610862565b8082825260208201915060208360051b850101925088831115610972575f5ffd5b6020840193505b82841015610994578335825260209384019390910190610979565b9450505050604084013567ffffffffffffffff8111156109b2575f5ffd5b6109be86828701610885565b915050925092509256fea26469706673582212209da8a9ff874542ed558a1a588833d8b51c195d809e823de93da6542c6ea7e1ff64736f6c634300081c003300000000000000000000000042000000000000000000000000000000000000210000000000000000000000007ed179e1196dfcaa6ae30a96dc697de7a2677f67
Deployed Bytecode
0x608060405260043610610071575f3560e01c806391db0b7e1161004c57806391db0b7e14610127578063ce46e0461461013a578063e49617e11461014c578063e60c35051461015f575f5ffd5b80633734256e1461009357806354fd4d50146100e357806388e5b2d914610104575f5ffd5b3661008f57604051631574f9f360e01b815260040160405180910390fd5b5f5ffd5b34801561009e575f5ffd5b506100c67f0000000000000000000000007ed179e1196dfcaa6ae30a96dc697de7a2677f6781565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100ee575f5ffd5b506100f7610172565b6040516100da9190610603565b610117610112366004610680565b610215565b60405190151581526020016100da565b610117610135366004610680565b6102e0565b348015610145575f5ffd5b505f610117565b61011761015a3660046106ec565b61039b565b61011761016d3660046106ec565b6103ad565b606061019d7f00000000000000000000000000000000000000000000000000000000000000016103c0565b6101c67f00000000000000000000000000000000000000000000000000000000000000036103c0565b6101ef7f00000000000000000000000000000000000000000000000000000000000000006103c0565b60405160200161020193929190610742565b604051602081830303815290604052905090565b5f61021e610450565b8382811461023f5760405163251f56a160e21b815260040160405180910390fd5b345f5b828110156102d0575f86868381811061025d5761025d610781565b905060200201359050828111156102875760405163044044a560e21b815260040160405180910390fd5b6102b489898481811061029c5761029c610781565b90506020028101906102ae9190610795565b50600190565b6102c4575f9450505050506102d8565b90910390600101610242565b506001925050505b949350505050565b5f6102e9610450565b8382811461030a5760405163251f56a160e21b815260040160405180910390fd5b345f5b828110156102d0575f86868381811061032857610328610781565b905060200201359050828111156103525760405163044044a560e21b815260040160405180910390fd5b61037f89898481811061036757610367610781565b90506020028101906103799190610795565b8261049b565b61038f575f9450505050506102d8565b9091039060010161030d565b5f6103a4610450565b60015b92915050565b5f6103b6610450565b6103a7823461049b565b60605f6103cc8361052c565b60010190505f8167ffffffffffffffff8111156103eb576103eb6107b4565b6040519080825280601f01601f191660200182016040528015610415576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461041f57509392505050565b336001600160a01b037f0000000000000000000000004200000000000000000000000000000000000021161461049957604051634ca8886760e01b815260040160405180910390fd5b565b5f6001600160a01b037f0000000000000000000000007ed179e1196dfcaa6ae30a96dc697de7a2677f67166104d7610100850160e086016107c8565b6001600160a01b0316146104ec57505f6103a7565b5f806104fc6101208601866107ee565b8101906105099190610904565b92509250508051825114610521575f925050506103a7565b506001949350505050565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061056a5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310610596576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106105b457662386f26fc10000830492506010015b6305f5e10083106105cc576305f5e100830492506008015b61271083106105e057612710830492506004015b606483106105f2576064830492506002015b600a83106103a75760010192915050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f83601f840112610648575f5ffd5b50813567ffffffffffffffff81111561065f575f5ffd5b6020830191508360208260051b8501011115610679575f5ffd5b9250929050565b5f5f5f5f60408587031215610693575f5ffd5b843567ffffffffffffffff8111156106a9575f5ffd5b6106b587828801610638565b909550935050602085013567ffffffffffffffff8111156106d4575f5ffd5b6106e087828801610638565b95989497509550505050565b5f602082840312156106fc575f5ffd5b813567ffffffffffffffff811115610712575f5ffd5b82016101408185031215610724575f5ffd5b9392505050565b5f81518060208401855e5f93019283525090919050565b5f61074d828661072b565b601760f91b8152610761600182018661072b565b9050601760f91b8152610777600182018561072b565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f823561013e198336030181126107aa575f5ffd5b9190910192915050565b634e487b7160e01b5f52604160045260245ffd5b5f602082840312156107d8575f5ffd5b81356001600160a01b0381168114610724575f5ffd5b5f5f8335601e19843603018112610803575f5ffd5b83018035915067ffffffffffffffff82111561081d575f5ffd5b602001915036819003821315610679575f5ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561085a5761085a6107b4565b604052919050565b5f67ffffffffffffffff82111561087b5761087b6107b4565b5060051b60200190565b5f82601f830112610894575f5ffd5b81356108a76108a282610862565b610831565b8082825260208201915060208360051b8601019250858311156108c8575f5ffd5b602085015b838110156108fa57803567ffffffffffffffff811681146108ec575f5ffd5b8352602092830192016108cd565b5095945050505050565b5f5f5f60608486031215610916575f5ffd5b83359250602084013567ffffffffffffffff811115610933575f5ffd5b8401601f81018613610943575f5ffd5b80356109516108a282610862565b8082825260208201915060208360051b850101925088831115610972575f5ffd5b6020840193505b82841015610994578335825260209384019390910190610979565b9450505050604084013567ffffffffffffffff8111156109b2575f5ffd5b6109be86828701610885565b915050925092509256fea26469706673582212209da8a9ff874542ed558a1a588833d8b51c195d809e823de93da6542c6ea7e1ff64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000042000000000000000000000000000000000000210000000000000000000000007ed179e1196dfcaa6ae30a96dc697de7a2677f67
-----Decoded View---------------
Arg [0] : eas (address): 0x4200000000000000000000000000000000000021
Arg [1] : _investorRegistry (address): 0x7Ed179E1196dfcaA6ae30A96DC697dE7A2677f67
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000004200000000000000000000000000000000000021
Arg [1] : 0000000000000000000000007ed179e1196dfcaa6ae30a96dc697de7a2677f67
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 32 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.