The Frictionless protocol is an institutional-grade venue built on EVM-compatible smart contracts for the issuance, distribution and settlement of digital securities in the private markets. The process involves dematerializing credit & infrastructure funds, ETFs or AMCs into risk-profiled future cash flow tokens, in the form of ERC-3643 digital securities which are aligned with the distribution schedule of the Manager.
Via strategies, Investors can invest in a diversified cross-section of funds using instant atomic settlement in attested 1:1 backed FIAT deposit tokens, which are banked with a G-SIB in Luxembourg.
This tokenization lego-brick approach ensures digital securities can be instantly composed into secondary trades, semi-liquid & automatic structured products and distributed between Investors in a privacy-protected mode for a few cents. All tokens within the protocol are permissioned tokens built under ERC-3643 specification for permissioned tokens to ensure that there is instant delivery versus payment, whilst ensuring the privacy of the Investor is protected. The Frictionless Markets APIs interact with these smart contracts to orchestrate the mint, transfer and burn of the various tokens in the protocol.
These contracts define the compliance layer for permissioned network participants (KYC/AML, Sanctions, PEP screening), the offering rules and the transfer rules for tokens, which ensures transfers are conducted in line with the legal and regulatory guardrails of MiFID II.
The compliance modules are upgradeable and are tied to specific tokens.
Participants
The Frictionless protocol is a market infrastructure for the issuance, trade, and settlement of digital securities in the private markets. The protocol caters for various roles and responsibilities both within the smart contracts and the API systems, enabling the various market functions to be performed according to the regulatory posture of Frictionless Markets S.à r.l, the legal issuer of digital securities in Luxembourg under MiFID II and the broader E.U.
Frictionless Markets S.à r.l and its securitization fund (FRICTIONLESS MARKETS SECURITIES FT) is the legal issuer of digital securities in compliance with MiFID II (2014/65/EU) regulation.
Frictionless Markets S.à r.l operates the PROTOCOL_ADMIN and PROTOCOL_TREASURY.
Where required and directed by a PERMISSIONED_MANAGER, Frictionless Markets S.à r.l provisions and/or operates a PERMISSIONED_CUSTODIAN on the protocol for the custody of securities or cash in accordance with the securitization laws of Luxembourg.
For more information on the legal structure of the FRICTIONLESS MARKETS SECURITIES FT, consult our
PROTOCOL_ADMIN
The protocol admin is the owner and deployer of the smart contracts. The Owner role is defined within the OpenZepplin context. The PROTOCOL_ADMIN is not permitted to custody any of the tokens within the protocol.
The ERC-3643 definition of the role is isOwner
PROTOCOL_TREASURY
Represents the treasury in the protocol. The PROTOCOL_TREASURY is an Agent under the definition of the ERC-3643 specification and is responsible for the lifecycle management of all tokens in the protocol. Frictionless Markets is the legal entity which is responsible for the treasury management of the non-co-mingled FIAT deposit & redemptions in multi-currency ledgers at G-SIB providers in Luxembourg under the role PROTOCOL_TREASURY.
The ERC-3643 definition of the role is isAgent
PERMISSIONED_CUSTODIAN
The Permissioned Custodian is the custodian address and OnChain Identity which can custody any of the Frictionless protocol tokens.
The ERC-3643 role is a Custom Compliance role.
PERMISSIONED_INVESTOR
A permissioned Investor in the protocol, is an investor who is compliant with the specification of the FrictionlessOnChainAssetToken and the private placement memorandum of the securitization structure and fund. The Frictionless protocol is open to accredited (professional client) investors only in compliance with (2014/65/EU) regulation, MiFID II. The onboarding of Investors is conducted off-chain, including KYC/AML, Subscription Agreement, etc, which are then added to the claim of the Investors' OnChainId.
The ERC-3643 role is a Custom Compliance role.
PERMISSIONED_MANAGER
A permissioned Manager in the protocol is a Manager or GP utilising both the technology protocol and the fund services of Frictionless Markets to issue their FrictionlessOnChainAssetToken. A PERMISSIONED_MANAGER may also interact with the FundDepositToken to accept & settle payments for Digital Securities.
The ERC-3643 role is a Custom Compliance role.
PERMISSIONED_FUND_ACCOUNTANT
A permissioned Fund Accountant in the protocol is an independent Fund Accountant with access to the underlying IBAN accounts for a FrictionlessFundDepositToken, so they can provide certified attestations for the balance of the accounts at regular intervals. A PERMISSIONED_FUND_ACCOUNTANT interacts with the IFrictionlessAttestationManager to provide this market feature.
The ERC-3643 role is a Custom Compliance role.
PERMISSIONED_CALCULATING_AGENT
A permissioned Calculating Agent in the protocol is an Agent who is permitted to calculate the market value of a FrictionlessOnChainAssetToken with the consent of the PERMISSIONED_MANAGER, so the cash waterfalls may be calculated for the Investors.
The role is not fully supported in the protocol yet.
The ERC-3643 role is a Custom Compliance role.
PERMISSIONED_TRANSFER_AGENT
A permissioned Transfer Agent in the protocol is an Agent who has the provision to transfer securities independently of the PROTOCOL_TREASURY.
The role is not fully supported in the protocol yet.
The ERC-3643 role is a Custom Compliance role.
Audit & Security
The smart contracts powering the Frictionless protocol have undergone a meticulous audit by Hacken.io, a renowned name in blockchain audit and security.
The Frictionless Protocol smart contracts have achieved a perfect 10/10 rating, attesting to the robustness and security of our blockchain infrastructure. This accomplishment reflects our unwavering commitment to ensuring the safety and trustworthiness of our platform.
10/10 - Security Score
10/10 - Code Quality Score
100% - Security Score
10/10 - Documentation Quality Score
The comprehensive audit report conducted by Hacken.io is now available for review at We encourage anyone interacting with the Frictionless protocol to explore the detailed findings, recommendations, and security measures outlined in the report.
Throughout the auditing process, we maintained a transparent and collaborative tracking with the Hacken.io team. This approach allowed us to address potential vulnerabilities promptly and work together to enhance the overall security of our smart contracts.
We are proud to announce that the are released under the MIT license. This open-source licensing model reflects our dedication to transparency, collaboration, and community involvement. The MIT license allows developers and stakeholders to freely use, modify, and distribute our smart contracts while providing clear guidelines on attribution and liability.
Frictionless Tokens
The Frictionless Tokens describe the tokens which are emitted by the Frictionless protocol to represent Asset, Securities and Deposits. These tokens are based on the ERC-3643 specification of IToken.
The following diagram describes the high-level interaction and composition of a Frictionless token.
Schematic relationship of Frictionless Tokens
Overview
The Frictionless smart contracts are an suite of available under the permissive which enable compliant digital securities transfer, payment and settlement on EVM-compatible blockchains, such as Avalance C-Chain, Ethereum or Polygon.
The Frictionless smart contracts extend the T-REX specification with specific features to operate private placements under MiFID II regulation.
The Frictionless protocol smart contracts are documented using the standard.
The Frictionless Tokens describe the tokens which are emitted by the Frictionless protocol to represent Asset, Securities and Deposits. These tokens are based on thespecification of IToken.
These contracts define the compliance layer for permissioned network participants (KYC/AML, Sanctions, PEP screening), the offering rules and the transfer rules for tokens, which ensures transfers are conducted in line with the legal and regulatory guardrails of MiFID II.
The Frictionless protocol is designed to automate cash operations across the lifecycle of a fund, part of this automation is the collection of contracted fee structures within a fund, such as management and/or performance fees. The smart contracts for transfer, ERC20 swap and FX swaps may be programmed to automatically collect fees for Managers, opening new revenue streams for Managers whilst ensuring the visibility of fees for Investors and Managers alike.
The Manager Contracts are the main entry points to the Frictionless protocol, they perform market functions such as permission management, treasury operations, issuance, transfer and settlement of securities, and attestations of deposits (proof-of-reserve) for the underlying of FrictionlessFundDepositTokens.
ERC20 Swaps were designed by the developers in the Frictionless protocol to risk off permissionless stablecoins such as USDC or USDT.
Permissionless are a great innovation from the crypto markets which were designed for permissionless crypto referencing to US Dollars, however handling stablecoins for traditional institutional partners is still a risky proposition.
Using the ERC20 Converter contracts, FrictionlessFundDepositTokens can be converted to/from stablecoins using the Frictionless protocol to help Managers accept stablecoins whilst off-loading their associated risks, such as de-peg events, underlying community bank reliance and liquidity risks.
The Frictionless Markets APIs are offered under commercial license terms if you wish to license the technology including the secure APIs, GraphQL data store, UI and automation services, please contact the team at https://www.frictionless.markets/ or via LinkedIn profile.
The IBasicFrictionlessToken Represents the base interface for Frictionless protocol tokens, this interface is used to determine a token type.
Functions
setFrictionlessTokenType
Sets the token type according to the specified enumeration
Parameters
Name
Type
Description
newTokenType_
FrictionlessTokenTypes
the token type to set
getFrictionlessTokenType
Returns the token type according to the specified enumeration
Returns
Name
Type
Description
<none>
FrictionlessTokenTypes
FrictionlessTokenTypes the token type according to the specified enumeration
The Frictionless protocol is essentially a decentralised system of privacy-protecting proofs and permissioned tokens that can only be transferred under tight controls in accordance with the regulatory rules of the underlying funds and securities which are tokenized.
The Frictionless protocol extends the ERC-3643 specification with specific features to operate private placements under MiFID II regulation. The are six main pillars of the Frictionless protocol as illustrated in the diagram below.
Frictionless protocol main smart contract pillars
Identity Management - based on OnChainId all participants in the Frictionless protocol are permissioned with specific roles, defining the actions and token classes they can interact with.
Compliance - based on the ERC-3643 specification, upgradable modules for compliance enable the compliant transfer of token classes in the protocol.
Frictionless Tokens - based on the ERC-3643 specification, these are the tokens circulated in the protocol to represent securities, assets, cash contributions, cash distributions and settlements.
Treasury Management - provides the smart contract functions to mint, transfer and burn token classes in the protocol.
Proof-of-Reserve - provides independent attestations over the currencies underpinning FrictionlessFundDepositTokens.
Transfer Agency - provides the controlled transfer of tokens between participants under strict compliance. This also includes the facility to swap tokens, such as stablecoins with FrictionlessFundDepositTokens or FX swaps of FrictionlessFundDepositTokens of various denominations.
The Smart Contract Docs cover these topics in depth with visual explanations of how each contract functions along with its NATSPEC documentation.
A Fund Deposit Token represents a permissioned Investors FIAT contribution to a specific fund IBAN in a denominated FIAT currency. The Fund Deposit Token is used as a means of payment and settlement. The Fund Deposit Token can only be transferred between permissioned Investors in the fund. A daily attestation of the fund IBAN serves to prove the 1:1 backing with FIAT. Exclusively under Frictionless Markets S.à.r.l issuance terms Investors holding a FrictionlessFundDepositToken have the legal right to the FIAT value held in the fund IBAN account.
Functions
setInitData
Sets the immutable data for the FrictionlessFundDepositToken
Parameters
Name
Type
Description
getCurrency
Get the currency the FIAT denomination of the deposit token.
Returns
Name
Type
Description
getDescription
Get the description the description of the deposit token.
Returns
Name
Type
Description
getFundIBAN
Get the IBAN which Frictionless Markets S.à.r.l holds a matching FIAT currency ledger with a G-SIB for this currency, attestations are provided on this IBAN. This is restricted to onlyAgent roles.
error throw if there is an attempt to modify the immutable data.
Structs
FFDImmutableData
Struct which represents the immutable data in the Token. Once set it cannot be modified.
Overview
Release v2.0.0 of the Frictionless Markets APIs built on OpenAPI specification on confidential compute cluster to ISO-27001 and SOC-2 specifications are due for release on Jan 24th 2024 (24/1/24).
Please check back with us or watch for announcements on our socials and LinkedIn.
The Frictionless platform is built on a microservice pattern, deployed on Confidential Google clusters for dedicated ISO-27001 secured environments, the stack is built to standard and interacts with the Frictionless via our internal proprietary Frictionless Chain Service built over the massively scalable and .
How it works
The Frictionless protocol is the technology enabler which translates real-world investments into legal, compliant and transferrable tokenized securities through a Luxembourg structure, operated by Frictionless Markets S.à r.l and its securitization structures.
Frictionless Markets S.à.r.l and its securitization fund (FRICTIONLESS MARKETS SECURITIES FT) is the legal issuer of digital securities in compliance with MiFID II (2014/65/EU) regulation.
High Level Architecture of Frictionless Protocol & APIs
Frictionless Markets APIs
Release v2.0.0 of the Frictionless Markets APIs built on OpenAPI specification on confidential compute cluster to ISO-27001 and SOC-2 specifications are due for release on Jan 24th 2024 (24/1/24).
Please check back with us or watch for announcements on our socials and LinkedIn.
Security & Access
Release v2.0.0 of the Frictionless Markets APIs built on OpenAPI specification on confidential compute cluster to ISO-27001 and SOC-2 specifications are due for release on Jan 24th 2024 (24/1/24).
Please check back with us or watch for announcements on our socials and LinkedIn.
initData
FFDImmutableData
the immutable data for the FrictionlessFundDepositToken
<none>
string
the currency the FIAT denomination of the deposit token.
<none>
string
the description the description of the deposit token
<none>
string
the IBAN which Frictionless Markets S.à.r.l holds a matching FIAT currency ledger with a G-SIB for this currency, attestations are provided on this IBAN.
function setInitData(FFDImmutableData calldata initData) external;
function getCurrency() external view returns (string memory);
function getDescription() external view returns (string memory);
function getFundIBAN() external returns (string memory);
For more information on the legal structure of the FRICTIONLESS MARKETS SECURITIES FT, consult our legal & fund documentation
There are many tokenization offerings in the market place and the industry is witnessing new entrants each with its respective niche and focus. The Frictionless protocol focus is specifically on the private markets and specifically on providing the legally compliant market infrastructure to enable Managers and GPs to tokenize their funds and offerings, whilst offering Investors a frictionless, low minimum, and transparent access point to the private markets on a global basis.
Core Layers
As a market infrastructure, the Frictionless protocol provides the three core layers to enable Investors to invest in the best private markets offerings on a global basis. These sections cover the basics of securitization, tokenization and distribution.
Core Layers of Frictionless protocol, Securitization, Tokenization and Distribution.
1. Securitization
The Frictionless Markets team supports a wide variety of securitizations in Luxembourg. The securitizations can be "true sale" or "synthetic" securitizations and are issued from bankruptcy remote and orphan entity-protected structures.
A securitization transaction involves establishing a securitization entity in Luxembourg to assume the risk associated with future cash flows tied to receivables, assets, or activities conducted by third parties known as the Underlying Assets. Simultaneously, the entity issues securities, typically in the form of notes, whose yield and value are connected to the performance of the Underlying Assets. These securities are then offered to professional investors on the financial markets in a tokenized format using the Frictionless protocol.
The Frictionless Markets team establishes and operates the securitization structures, providing the fund administration, fund structuring, cash operations and fund reporting services under Luxembourg securitization law.
2. Tokenization
The Frictionless protocol includes:
A suite of smart contracts to represent:
Funds/Notes - Frictionless OnChain Assets: The FrictionlessOnChainAssetToken represents a listed fund with the informational and legal rights to the underlying. This includes all the informational rights on the underlying and its associated maturity. A FrictionlessOnChainAssetToken is issued as a digital twin for each specific note in a compartment within the Frictionless Markets fund structure.
Cash - Frictionless Deposit Tokens: A FrictionlessFundDepositToken represents a permissioned Investors FIAT contribution to a specific fund IBAN in a denominated FIAT currency. The FrictionlessFundDepositToken is used as a means of payment and settlement record. The FrictionlessFundDepositToken can only be transferred between permissioned Investors and Managers in the fund as a record of FIAT transfers within the Fund. A daily attestation of the fund IBAN serves to prove the 1:1 backing with FIAT. Market participants holding a FrictionlessFundDepositToken have the legal claim to the FIAT value held in the fund IBAN account under the final terms of the financial instrument issued by the note tracking the FrictionlessFundDepositToken.
Securities - Frictionless Digital Security Tokens: This is the which represents the future cash flow from the FrictionlessOnChainAssetToken and is purchased by the Investor using FrictionlessFundDepositToken's. These digital securities are permissioned and transferable between permissioned Investors in a permissioned market. This token is linked to the FrictionlessOnChainAssetToken and denominated in a FIAT currency at a future date for settlement.
Smart contracts to execute the of Frictionless tokens in primary and secondary transactions
Smart contracts to ERC20 tokens (stablecoins) to/from Frictionless Deposit Tokens, enabling Managers to risk off stablecoin contributions to their respective funds/
Smart contracts to Frictionless Deposit Tokens of different FIAT denominations using spot and forward rates, enabling Investors to invest and settle in multiple currencies.
Smart contracts to manage the of market participants in accordance with regulation.
APIs and a Tokenization Engine to orchestrate and automate complex Manager workflows such as:
Subscriptions
Capital Calls
Wallet Infrastructure enabling the custody of tokenized funds/notes, the collection of fees, custody of ERC20 stablecoins for the PROTOCOL_TREASURY and the wallet infrastructure required to sign and execute transactions on the blockchain.
The Frictionless Markets team operates the protocol, granting access to Managers to tokenize their funds and automate their fund administration services from the Frictionless Markets Manager Interface, API or smart contracts.
3. Distribution
Managers can onboard Investors directly or link into permissioned distribution agents on the Frictionless protocol to distribute their tokenized securities on a global basis., these include:
Private Placement Agents
Global Wealth Advisors
Private Banks
Digital Security Exchanges
The distribution layer of the Frictionless protocol enables Investors to onboard into tokenized funds using their OnChainId, direct KYC/AML subscription or via reliance letter.
Investors invest via subscriptions or subscription contracts to the tokenized fund/note in accordance with MiFID II regulation.
The investment and settlement of tokenized securities are carried out using Frictionless Deposit Tokens, which is a non-invasive and seamless conversion between FIAT contributions or settlement and their tokenized representation.
The Frictionless Markets team operates the protocol, granting access to Distribution Agents and their Investor base to a wide variety of tokenized funds from the world's best GPs and Managers.
Distribution Agents can manage:
Subscriptions to Funds for their Investor base.
Capital Calls and reporting for their Investor base.
Cash Distributions and reporting for their Investor base.
Portfolio Compositions for their Investor base.
Supported Securitizations
Securitization encompasses a wide range of asset types, including:
Receivables such as loans
Liquid assets like bonds or securities
Illiquid assets including private equity and real estate
Derivative instruments
Intellectual property generating royalty streams
Cash flow associated with risk or contractual agreements
Shares in other entities, PE, Credit, Infrastructure funds, or deals
Frictionless Markets supports the issuance of Notes, Tracker Certificates, and Actively Managed Certificates in multiple currencies. In general, the Frictionless Markets team and the Frictionless protocol support the following securitization & tokenization use cases:
For more information on the securitization benefits from Frictionless Markets and an in-depth understanding of our offerings, consult our legal & fund documentation.
Lifecycle of a Transaction
The act of correctly securitizing an undertaking, legally and in compliance with the laws of Luxembourg, and thereafter tokenizing into legally compliant tokenized (digital) securities for distribution to permissioned Investors is a complex end-to-end transaction. This section covers the high-level details of the lifecycle of a transaction which holds true for any type of tokenized offering undertaken by Frictionless Markets.
Frictionless Protocol: Basic Token Lifecycle
Establishment of the correct Luxembourg securitization structure.
The Frictionless Markets team will create the PPM (private placement memorandum) and the Final Terms for the securitization undertaking.
The Frictionless Markets team creates the compartment, bank accounts of the compartment and the permissioning/provisioning of the necessary wallet infrastructure to execute the tokenization.
All relevant statutory reporting and regulatory obligations for the structure are handled by the Frictionless Markets team, including AML6, SARs, CRS, FATCA, FATF, ManCo Reporting, etc.
Tokenization of the undertakings.
The Manager is permissioned on the Frictionless protocol.
Managers can onboard Investors via subscriptions or subscription contracts to the tokenized fund/note in accordance with MiFID II regulation.
Distribution of the tokenized securities.
Managers can onboard Investors directly or link into permissioned distribution agents on the Frictionless protocol to distribute their tokenized securities on a global basis.
Capital Calls* automatically execute upon Investors' subscriptions to a fund/funds, converting FIAT contributions to Frictionless Deposit Tokens and releasing Frictionless Digital Securities to record the transaction on-chain.
Frictionless FX Swaps
Frictionless FX Swaps enable Investors to invest instantly, securely and risk-free at super low cost in multiple currencies.
The FX Swap contracts in the Frictionless protocol provide an instant/atomic swap of a currency pair at a quoted spot or forward rate.
Built on cash custody with G-SIB banking providers and FX partners in the EU, the list of supported currencies and currency pairs is maintained in our Frictionless Institutional Deposit Tokens listing.
Frictionless FX Swaps remove the complexity of investing in multi-currency, whilst providing ultimate flexibility and transparency of FX rates and settlement.
FX Swaps work by automating the treasury operations in an FX transaction, namely:
Establishment of optional FX fees to be paid by the seller of currency A,
Utilization of the buying rate for currency Z in the swap. The rate utilized in the Frictionless protocol is obtained from our FX partners, the Frictionless Markets team support both spot and forward rates for FX Swaps offering clients the ultimate flexibility and transparency in FX swaps.
An example of a live FX Swap on the Avalanche C-Chain is at .
In this FX Swap USD was sold for 5,000 EUR. The rate used was a spot rate provided to the Frictionless Markets team. In the block explorer, you can see the collection of fees, burn of fsUSD and mint of fsEUR. The swap and fee collection ran as a single atomic transaction and cost 0.80 USD to execute on the Avalanche C-Chain.
ERC20 Swaps
ERC20 Swaps were designed by the developers in the Frictionless protocol to risk off permissionless stablecoins such as USDC or USDT.
Permissionless are a great innovation from the crypto markets which were designed for permissionless crypto referencing to US Dollars, however handling stablecoins for traditional institutional partners is still a risky proposition.
Using the ERC20 Converter contracts, FrictionlessFundDepositTokens can be converted to/from stablecoins using the Frictionless protocol to help Managers accept stablecoins whilst off-loading their associated risks, such as de-peg events, underlying community bank reliance and liquidity risks.
Automated Fee Collection
The Frictionless protocol is designed to automate cash operations across the lifecycle of a fund, part of this automation is the collection of contracted fee structures within a fund, such as management and/or performance fees.
The smart contracts for securities exchange, transfer, ERC20 swap and FX swaps may be programmed to automatically collect fees for Managers, opening new revenue streams for Managers whilst ensuring the visibility of fees for Investors and Managers alike.
The following diagram illustrates the design of the fee module, which enables the definition of fees to be automatically collected by a defined fee recipient during any of the value exchange functions in the protocol.
Execution of the swap as a single atomic transaction whereby currency A and currency Z are burned and minted from/to two counterparties with the automatic collection of optional fees. This operation can only be directed by the PROTOCOL_TREASURY to avoid market manipulation of FX rates.
Live FX Swap - fsUSD for fsEUR (spot rate from Alpha FX)
Cash Distributions
Portfolio Compositions
The Manager can issue notes, and capital calls*, and run cash distributions** from the Frictionless Markets UI, via integration with the Frictionless Markets API or directly via the smart contracts.
Cash Distributions ** automatically distribute income and return of the underlying to the Investors, settling the Frictionless Digital Securities with Frictionless Deposit Tokens, thereafter handling the FIAT settlement in the securitization transaction.
The PROTOCOL_TREASURY manages the on/off ramp of the ERC20 stablecoin, such as USDC/USDT within its fund structures of FRICTIONLESS MARKETS SECURITIES FT.
The availability of a valid configured ERC20 token for conversion to/from FrictionlessFundDepositToken along with the associated fees is transparent, any market participant may query the smart contract.
The principle of an ERC20 Swap is simple.
Schematic of a Frictionless ERC20 (USDC stablecoin) Swap
The PROTOCOL_ADMIN defines the valid token pairs which are convertible on a 1:1 basis.
Fees can be optionally defined for the conversion to/from the ERC20 token.
The holder (Investor) of ERC20 tokens invokes the convertFromERC20function of the smart contract, the ERC20 tokens are sent to the PROTOCOL_TREASURY and a matching amount of FrictionlessFundDepositToken is minted and sent to the holder (Investor).
If the Investor wishes to convert their FrictionlessFundDepositToken to a valid configured ERC20 token, such as USDC/USDT, then they can invoke the convertToERC20function of the smart contract. In this case, the PROTOCOL_TREASURY will receive the FrictionlessFundDepositToken and burn it, transferring the matching amount of ERC20 (less any fees) to the Investor.
An example of two live ERC20 swaps on the Avalanche C-Chain are;
In these swaps, you can observe the collection of optional fees and the atomic settlement of the swap of the fsUSD tokens with USDC into the PROTOCOL_TREASURY.
Frictionless ERC20 Swap - USDC for fsUSD with automatic fee collection
Frictionless ERC20 Swap - fsUSDC for USDC with no fee collection
Arctitecture of the Frictionless Fee Module
Fees may be configured to be collected in the following transactions:
P2P (bi-lateral) transfer of tokens between permissioned counterparties, for example, a direct transfer of securities between two Investors, such as a secondary trade.
Exchange of securities, executed by the protocol during a primary issuance, in the form of management fees upon committed capital or deployed capital.
Settlement of securities, executed by the protocol or by the Investor.
Conversion of an ERC20 token to/from a FrictionlessFundDepositToken, for example, converting USDC to the USD equivalent FrictionlessFundDepositToken or conversion of another ERC20 collateral.
FX swap of FrictionlessFundDepositToken of different currencies.
The fee architecture permissions the protocol admin to establish fees, this ensures that the market integrity for fees is maintained, for example, the FX rates are taken from our FX partner's spot and forward rates quoted, and the conversion of ERC20 stablecoins such as USDC and USDT to it's USD equivalent FrictionlessFundDepositToken.
the FeeInfo to validate. throws AbstractFeeModuleInvalidFeeRecipient if the feeRecipientAddr is a zero address throws AbstractFeeModuleInvalidFee if the feeInBps is not in the valid range (ZERO_FEES_IN_BPS to MAX_FEES_IN_BPS)
This is the permissioned & transferable digital security which represents the future cash flow from the FrictionlessOnChainAssetToken and is purchased by the Investor using FrictionlessFundDepositTokens. These digital securities are permissioned and transferable between permissioned Investors in a permissioned secondary market. This token is linked to the FrictionlessOnChainAssetToken and denominated in a FIAT currency at a future date for settlement.
Functions
setInitData
Sets the immutable data for the FrictionlessDigitalSecurityToken
Parameters
Name
Type
Description
initData
FDSImmutableData
the immutable data for the FrictionlessDigitalSecurityToken
setUpdateData
Sets the updatable data for the FrictionlessDigitalSecurityToken
Parameters
Name
Type
Description
mutableData
FDSMutableData
the updatable data for the FrictionlessDigitalSecurityToken
getCurrency
Get the baseCurrency is the FIAT denomination of the digital security, this is the currency the FrictionlessOnChainAssetToken is issued in.
Returns
Name
Type
Description
<none>
string
the baseCurrency is the FIAT denomination of the digital security, this is the currency the FrictionlessOnChainAssetToken is issued in.
getTokenType
Get the type of the token as defined in the enum FrictionlessDigitalSecurityTokenType.
Returns
Name
Type
Description
<none>
FrictionlessDigitalSecurityTokenType
the type of the token as defined in the enum.
getOnChainAssetAddress
Get the onChainAssetAddress the address of the FrictionlessOnChainAssetToken for which this token is a future cash distribution.
Returns
Name
Type
Description
<none>
address
onChainAssetAddress the address of the FrictionlessOnChainAssetToken for which this token is a future cash distribution.
The Frictionless protocol is designed and built on the Avalanche C-Chain, for public-permissioned issuance, trade and settlement of private markets digital securities in compliance with the blockchain & securitization laws of Luxembourg.
Built on Avalanche!
The Avalanche C-Chain network is the Frictionless Markets Treasury Chain, which means that issuances and settlement of Frictionless tokens are carried out on Avalanche.
Always check that the smart contracts you interact with are valid contracts issued by the Frictionless Markets Protocol Administrator.
The PROTOCOL_ADMIN address is 0x55749224f94d79687Ba3955db2180d7C5D7D2409
Deployed Contracts
The Frictionless has deployed at the following contract addresses.
The Frictionless protocol contracts are deployed at the following addresses on Avalanche.
Interface defining the token factory for all tokens in the Frictionless protocol.
Institutional Deposit Tokens
The attestations for Frictionless Institutional Deposit Tokens are proved by the PERMISSIONED_FUND_ACCOUNTANT (Creatrust Luxembourg) and are publicly available at
Always check that the smart contracts you interact with are valid contracts issued by the Frictionless Markets Protocol Administrator.
Any other address purporting to offer the Frictionless protocol is not valid.
If you have any queries or wish to report any suspected issues, please contact the protocol admin team via [email protected]
Sets the Treasury Manager to be the specified address.
Parameters
Name
Type
Description
newTreasuryManager_
address
the addresses of the treasury manager to set throws FrictionlessTokensFactoryZeroAddress if the newTreasuryManager_ is a zero address
deployFundDepositToken
Deploys the FrictionlessFundDepositToken contract as a proxy
Parameters
Name
Type
Description
tokenOwner_
address
The owner of the deployed contract
baseTokenInitParams_
BaseTokenInitParams
the base contract data to deploy a Frictionless token contract
initData_
IFrictionlessFundDepositToken.FFDImmutableData
the immutable data for the FrictionlessFundDepositToken
Returns
Name
Type
Description
tokenProxyAddr_
address
the address of the deployed token contract FrictionlessFundDepositToken throws FrictionlessTokensFactoryNotATreasuryManager if the msg.sender is not the treasury manager emits FrictionlessTokenDeployed event upon successful deployment of the token contract.
deployDigitalSecurityToken
Deploys the FrictionlessDigitalSecurityToken contract as a proxy
Parameters
Name
Type
Description
tokenOwner_
address
The owner of the deployed contract
baseTokenInitParams_
BaseTokenInitParams
the base contract data to deploy a Frictionless token contract
the immutable data for the FrictionlessDigitalSecurityToken
Returns
Name
Type
Description
tokenProxyAddr_
address
the address of the deployed token contract FrictionlessDigitalSecurityToken throws FrictionlessTokensFactoryNotATreasuryManager if the msg.sender is not the treasury manager emits FrictionlessTokenDeployed event upon successful deployment of the token contract.
deployOnChainAssetToken
Deploys the FrictionlessOnChainAssetToken contract as a proxy
Parameters
Name
Type
Description
tokenOwner_
address
The owner of the deployed contract
baseTokenInitParams_
BaseTokenInitParams
the base contract data to deploy a Frictionless token contract
specData_
IFrictionlessOnChainAssetToken.FOCASpecData
the immutable specification data for the FrictionlessOnChainAssetToken
Returns
Name
Type
Description
tokenProxyAddr_
address
the address of the deployed token contract FrictionlessOnChainAssetToken throws FrictionlessTokensFactoryNotATreasuryManager if the msg.sender is not the treasury manager emits FrictionlessTokenDeployed event upon successful deployment of the token contract.
treasuryManager
returns the address of the treasuryManager
Returns
Name
Type
Description
<none>
address
the address of the treasuryManager
existingFrictionlessTokens
Checks whether a given token address is an existing frictionless token
Parameters
Name
Type
Description
tokenAddr_
address
the address of the token to check
Returns
Name
Type
Description
<none>
bool
A boolean indicating whether the token is an existing frictionless token
Events
FrictionlessTokenDeployed
Event emitted upon successful deployment of a compliance contract.
Errors
FrictionlessTokensFactoryZeroAddress
error thrown if an attempt to set a zero address contract during function setTreasuryManager
FrictionlessTokensFactoryNotATreasuryManager
error thrown if the msg.sender is not the treasury manager during the functions deployFundDepositToken, deployDigitalSecurityToken, or deployOnChainAssetToken
Structs
BaseTokenInitParams
Struct to represent the base contract data to deploy a Frictionless token contract.
The PROTOCOL_ADMIN address is 0x55749224f94d79687Ba3955db2180d7C5D7D2409
Any other address purporting to offer the Frictionless protocol is not valid.
If you have any queries or wish to report any suspected issues, please contact the protocol admin team via [email protected]
Deployed Institutional Deposit Tokens
The Frictionless PROTOCOL_ADMIN has deployed the following FrictionlessFundDepositTokens.
The Frictionless Institutional Deposit Tokens are deployed at the following token addresses on Avalanche.
Currency
Frictionless Token Address
USD
EUR
Structure of Frictionless Institutional Deposit Tokens
The Frictionless Institutional Deposit Token (FricitonlessFundDepositToken) is designed as a method of recording a FIAT contribution for a PERMISSIONED_INVESTOR into a listed fund on the Frictionless protocol.
Neither Frictionless Markets nor its parent company DEFYA HOLDINGS nor any subsidiaries actively manage currency contributions for Investors or permissioned participants in the protocol.
All investment decisions must made exclusively by Investors or their appointed wealth advisors or agents.
The Frictionless Markets team passively manages a collection of open-ended fund structures which are designed to securitise the currency contributions, so thereafter these tokens can be used to record payment, settlement and trade in tokenized securities from funds listed on the Frictionless protocol.
The following high-level diagram describes the main participants and their high-level interaction with the protocol.
Passive Securitization Structure of Frictionless Institutional Deposit Tokens
For more information on the legal structure of the FRICTIONLESS MARKETS SECURITIES FT, consult our legal & fund documentation
Implementation of the storage of the underlying OnChain Asset and it's data.
Functions
setSpecificationData
Sets the specData data for the FrictionlessOnChainAssetToken. throws FrictionlessOnChainAssetTokenUnableToUpdateData This data is immutable, an attempt to modify will generate the error FrictionlessOnChainAssetTokenUnableToUpdateData
Parameters
Name
Type
Description
specData
FOCASpecData
the specData data for the FrictionlessOnChainAssetToken
setIssuanceData
Sets the issuanceData data for the FrictionlessOnChainAssetToken throws FrictionlessOnChainAssetTokenUnableToUpdateData This data is immutable, an attempt to modify will generate the error FrictionlessOnChainAssetTokenUnableToUpdateData
Parameters
Name
Type
Description
issuanceData
FOCAIssuanceData
the updatable data for the FrictionlessOnChainAssetToken
setUpdateData
Sets the updatable data for the FrictionlessOnChainAssetToken
Parameters
Name
Type
Description
updateData
FOCAUpdateData
the updatable data for the FrictionlessOnChainAssetToken
getSpecificationData
Get the specData data for the FrictionlessOnChainAssetToken.
Returns
Name
Type
Description
<none>
FOCASpecData
the specData data for the FrictionlessOnChainAssetToken
getIssuanceData
Get the issuanceData data for the FrictionlessOnChainAssetToken.
Returns
Name
Type
Description
<none>
FOCAIssuanceData
the issuanceData data for the FrictionlessOnChainAssetToken
getUpdateData
Get the updateData data for the FrictionlessOnChainAssetToken.
Returns
Name
Type
Description
<none>
FOCAUpdateData
the updateData data for the FrictionlessOnChainAssetToken
getCurrency
Get the currency the FrictionlessOnChainAssetToken is issued in.
Returns
Name
Type
Description
<none>
string
the currency the FrictionlessOnChainAssetToken is issued in.
Errors
FrictionlessOnChainAssetTokenUnableToUpdateData
error throw if there is an attempt to modify the immutable data.
Structs
FOCASpecData
The specification data for the FrictionlessOnChainAssetToken, this is an immutable data struct.
FOCAIssuanceData
The issuance data for the FrictionlessOnChainAssetToken, this is an immutable data struct.
FOCAUpdateData
The uopdatable data for the FrictionlessOnChainAssetToken.
Enums
FrictionlessOnChainAssetSchedule
Enum for the schedule of the payments by the Manager, either pro_rat or coupon/bullet style.
FrictionlessOnChainAssetPaymentFrequency
Enum for the periodicity of payments by the Manager
FrictionlessOnChainAssetYieldType
Enum for the yield for this FrictionlessOnChainAssetToken is a fixed/floating rate
FrictionlessOnChainAssetPriceStatus
Enum for the price quote status obtained at auction
FrictionlessOnChainAssetStatus
Enum for the current status of the FrictionlessOnChainAssetToken. Updated over time by the Treasury
FrictionlessOnChainAssetRiskGrade
Enum for the current S&P style riskGrade of the FrictionlessOnChainAssetToken. Updated over time by the Manager/Treasury/Risk Oracle.
thrown during bindToken or unBindToken if the caller is not the owner or the bound token address
FrictionlessModularComplianceCallerNotAToken
thrown if the the msg.sender is not the bound token address during modifier onlyToken
Protocol Roadmap
The Frictionless protocol is an upgradable and extensible market infrastructure. The protocol is developed by the IP company DEFYCA Labs S.à.r.l, which develops the smart contract suite under the permissive MIT license.
To contribute or request features to the protocol, please consult the CONTRIBUTING documentation for the smart contract suite.
The roadmap for the Frictionless protocol smart contracts includes:
Fundamental Analysis - Using the PERMISSIONED_CALCULATING_AGENT role to provide fundamental analysis on underlying portfolios via smart contracts in privacy-protecting mode.
Qualified Transfer Agents - Opening access to 3rd party transfer agents to execute the transfer and settlement of securities issued on the Frictionless protocol in accordance with local regulatory posture.
Portfolio Re-Balancers - A suite of smart contracts which enable PERMISSIONED_INVESTORS to automatically re-balance their portfolio of investments according to their specific investment goals.
The broader roadmap includes features which are commercially developed by Frictionless Markets S.à.r.l, which can be requested via the site.
maximum number of allowable modules which can be bound. throws FrictionlessModularComplianceMaxModuleCountReached if the maximum amount of modules has been reached as per the maxModulesCount throws FrictionlessModularComplianceModuleIsAlreadyBound if the module is already bound throws FrictionlessIsZeroAddress if the module address is a zero address throws FrictionlessModularComplianceZeroMaxModulesCount if an attempt to set the maximum number of allowable modules to zero is made in updateMaxModulesCount emits ModulesAdded upon sucessful addition emits MaxModulesCountUpdated upon successful update of the maximum modules count.
newMaxModulesCount_
uint256
maximum number of allowable modules which can be bound. throws FrictionlessModularComplianceZeroMaxModulesCount if an attempt to set the maximum number of allowable modules to zero is made in updateMaxModulesCount emits MaxModulesCountUpdated upon successful update of the maximum modules count.
modulesToAdd_
address[]
the array of module addresses to be added throws FrictionlessModularComplianceMaxModuleCountReached if the maximum amount of modules has been reached as per the maxModulesCount throws FrictionlessModularComplianceModuleIsAlreadyBound if the module is already bound throws FrictionlessIsZeroAddress if the module address is a zero address emits ModulesAdded upon sucessful addition
modulesToRemove_
address[]
the array of module addresses to be removed throws FrictionlessModularComplianceModuleDoesNotExist if module for the given address is not already bound emits ModulesRemoved upon sucessful removal
<none>
uint256
maximum number of allowable modules which can be bound.
function init(address[] calldata modules_, uint256 maxModulesCount_) external;
function updateMaxModulesCount(uint256 newMaxModulesCount_) external;
function addModules(address[] calldata modulesToAdd_) external;
function removeModules(address[] calldata modulesToRemove_) external;
function maxModulesCount() external view returns (uint256);
The IFrictionlessPermissionsManager is responsible for the management of permission of the various participants in the Frictionless protocol. The roles and responsibilities are defined in the public README for the Frictionless protocol at https://gitlab.com/dfyclabs/protocol/dfyclabs-tokens/-/blob/main/README.md?ref_type=heads#roles-responsibilities
Functions
isPermissioned
Validates if a wallet address is permissioned in the Frictionless protocol
Parameters
Name
Type
Description
Returns
Name
Type
Description
registerIdentity
Registers a users wallet address as an OnChainId (Identity) to the Frictionless protocol. This Identity is used when permissioning a user to the protocol by invoking the addUser function later.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getIdentity
Gets a users OnChainId (Identity) in the Frictionless protocol.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getClaimMsgHash
Get the signed claimData message to be used in the addUser function. The message must be signed using the PK of the ClaimIssuer (PROTOCOL_ADMIN)
Parameters
Name
Type
Description
Returns
Name
Type
Description
hasClaim
verify if the userAddress is permissioned in the Frictionless protocol and has a valid claim
Parameters
Name
Type
Description
Returns
Name
Type
Description
addUser
Adds a user's OnChainId (Identity) to the Frictionless protocol along with its associated claim data. The Identity is created by invoking the registerIdentity function first.
Parameters
Name
Type
Description
Returns
Name
Type
Description
removeUser
Removes a user from the Frictionless protocol along with its associated claim data.
Parameters
Name
Type
Description
Returns
Name
Type
Description
Events
FrictionlessPermissionedUserAdded
Emitted when a user is added to the Frictionless protocol. This event is emitted by the addUser function.
FrictionlessPermissionedUserRegistered
Emitted when a user is registered in the Frictionless protocol. This event is emitted by the registerIdentity function.
FrictionlessPermissionedUserRemoved
Emitted when a user is removed in the Frictionless protocol. This event is emitted by the removeUser function.
Errors
FrictionlessIsZeroAddress
throws if specific address is zero.
FrictionlessInvalidPermissionForTreasury
throws if treasury tries to add or remove treasury.
FrictionlessUserIsNotPermssionedInvestor
throws if user is not a permissioned investor
Structs
Claim
the internal struct defining a Claim for a PERMISSIONED_USER in the protocol. Used to submit claims for the OnChainId by the ClaimIssuer.
Enums
FrictionlessPermissionedUser
Enum of the Frictionless protocol participants.
newTreasuryManager_
address
the address of the treasury manager to set throws FrictionlessComplianceFactoryZeroAddress if the newTreasuryManager_ is a zero address
newModularComplianceImpl_
address
the address of the modular compliance implementation
updateSupportedComplianceDataArr_
UpdateSupportedComplianceData[]
the set of supported modular compliance modules.
updateModularComplianceDataArr_
UpdateModularComplianceData[]
the modular compliance data.
tokenType_
IBasicFrictionlessToken.FrictionlessTokenTypes
The Frictionless token type as defined by IBasicFrictionlessToken.FrictionlessTokenTypes
<none>
address
the address of the deployed compliance contract for the specified Frictionless token type throws FrictionlessComplianceFactoryNotATreasuryManager if the msg.sender is not the treasury manager emits FrictionlessComplianceDeployed event upon successful deployment of the compliance contract.
<none>
address
the address of the treasuryManager
<none>
ProxyBeacon
the ProxyBeacon of the ModularCompliance
<none>
address
the address of the ModularCompliance
modularComplianceAddr_
address
the address of the ModularComplianceImpl
<none>
IBasicFrictionlessToken.FrictionlessTokenTypes
the address of the ModularCompliance
tokenType_
IBasicFrictionlessToken.FrictionlessTokenTypes
the type of token as defined by the IBasicFrictionlessToken.FrictionlessTokenTypes enumerated type
<none>
uint256
the amount of supported compliances
tokenType_
IBasicFrictionlessToken.FrictionlessTokenTypes
the type of token as defined by the IBasicFrictionlessToken.FrictionlessTokenTypes enumerated type
<none>
address[]
the array of supported compliances
tokenType_
IBasicFrictionlessToken.FrictionlessTokenTypes
the type of token as defined by the IBasicFrictionlessToken.FrictionlessTokenTypes enumerated type
moduleToCheck_
address
the address of the modular compliance contract to verify
<none>
bool
true if the compliance module supports the Frictionless token type, otherwise false
modularComplianceAddr_
address
the address of the ModularCompliance contract
<none>
bool
true if the address provided is a ModularCompliance contract, otherwise false
string
the URI of the off-chain claim for the user. i.e. The Frictionless Markets graphQL endpoint requires The msg.sender to be the Owner if the userType is the PROTOCOL_TREASURY requires The msg.sender to have the TREX Agent permissions (PROTOCOL_TREASURY or PROTOCOL_ADMIN) to add any user
userAddress
address
the wallet address to verify
<none>
bool
true if the address is permissioned in the Frictionless Protocol.
userAddress
address
the address of the user's wallet to register
userISOCountry
uint16
the ISO 3166-1 numeric code of the user, can be the place of residence or the location KYC/AML onboarding was undertaken. requires The msg.sender to have the TREX Agent permissions (PROTOCOL_TREASURY or PROTOCOL_ADMIN)
<none>
address
address the address of the user's OnChainId (Identity) with the associated claims.
userAddress
address
the address of the user's wallet to register requires The msg.sender to have the TREX Agent permissions (PROTOCOL_TREASURY or PROTOCOL_ADMIN)
<none>
address
address the address of the user's OnChainId (Identity) with the associated claims.
Interface defining the frictionless conversion and atomic swapping of any FrictionlessFundDepositToken currency pair on the Frictionless protocol. The FX rates are set from the live spot & forward FX partners on the protocol.
Functions
setFXDeskFeeAddr
Sets the address of the FXDesk fee recipient Only Owner (PROTOCOL_ADMIN) can call this function
Parameters
Name
Type
Description
setSwapFees
Set the swap fees for the swaps of a token pair. The fees can be any combination of zero (0%) or upto 10000 bps (100%) on any directional transfer. Fees can only be set by the Owner (PROTOCOL_ADMIN).
Parameters
Name
Type
Description
setTokenFee
Set the fee associated with the swap of a Token and manages the mapping of the key to this set of Fees. Can only be set by the Owner (PROTOCOL_ADMIN).
Parameters
Name
Type
Description
swapTokens
Swaps tokens between addresses at a specified exchange rate Only PROTOCOL_TREASURY can call this function
Parameters
Name
Type
Description
fxDeskFeeAddr
Retrieves the address of the FXDesk fee recipient
Returns
Name
Type
Description
treasuryManager
Retrieves the Frictionless Treasury Manager contract
Returns
Name
Type
Description
permissionManager
Retrieves the Frictionless Permissions Manager contract
Returns
Name
Type
Description
getSwapFeesInfo
get the tokenFeeInfo set for the fees associated per token in an exchange.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getSwapFeeKeys
Generates keys based on the packed encoding of the addresses of sets of tokens using the keccak256 hashing function. Used to store tokenFees in mappings.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getTokenFeeKey
Generates a key based on the packed encoding of the addresses of both tokens using the keccak256 hashing function. Used to store tokenFees in mappings.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getSellingTokensAmount
Calculates the amount of selling tokens based on the buying amount and exchange rate
Parameters
Name
Type
Description
Returns
Name
Type
Description
Events
FrictionlessFXTokensSwapped
Event emitted upon successful token swaps
Errors
FrictionlessFXSwapInvalidTokenAddresses
error thrown during setSwapFees if token adresses are invalid (zero addresses, equals addresses and etc.).
FrictionlessFXSwapInvalidFeeRecipientAddr
error thrown during setSwapFees, setTokenFee and swapTokens if the fxDeskFeeRecipient doesn't equal to the stored fxDeskFeeAddr
FrictionlessFXSwapNotEnoughPermissions
error thrown during swapTokens if the msg.sender is not a PROTOCOL_TREASURY.
Structs
FrictionlessTokenFXFeeInfo
Structure representing token fee information including the token address and fee information
The exchange rate of the token being bought to the token being sold
newFXDeskFeeAddr_
address
The new address of the FXDesk fee recipient
token0FeeInfo_
FrictionlessTokenFXFeeInfo
The fees associated with the token0 (first token) in the token pair during the swap.
token1FeeInfo_
FrictionlessTokenFXFeeInfo
The fees associated with the token1 (second token) in the token pair during the swap. throws FrictionlessFXSwapInvalidTokenAddresses if the token addresses are invalid. throws FrictionlessFXSwapInvalidFeeRecipientAddr if the feeRecipientAddr doesn't equal to the fxDeskFeeAddr. throws AbstractFeeModuleInvalidFeeRecipient if the feeRecipientAddr is a zero address throws AbstractFeeModuleInvalidFee if the feeInBps is not in the valid range (ZERO_FEES_IN_BPS to MAX_FEES_IN_BPS) emits FrictionlessFeeSet upon completion of the setting of the fee info for the token in either set of fees
tokenFeeKey_
bytes32
The key, generated by the function getTokenFeeKey, which is used to map a specific swap polarity for tokens.
tokenFeeInfo_
FrictionlessTokenFXFeeInfo
The fees associated with the swap of token, used in the calculation and disbursement of fees during swap of a token pair. throws FrictionlessFXSwapInvalidTokenAddresses if the token addresses are invalid. throws FrictionlessFXSwapInvalidFeeRecipientAddr if the feeRecipientAddr doesn't equal to the fxDeskFeeAddr. throws AbstractFeeModuleInvalidFeeRecipient if the feeRecipientAddr is a zero address throws AbstractFeeModuleInvalidFee if the feeInBps is not in the valid range (ZERO_FEES_IN_BPS to MAX_FEES_IN_BPS) emits FrictionlessTokenFeeSet upon completion of the setting of the fee info for the token
sellingTokenAddr_
address
The address of the token to be sold
buyingTokenAddr_
address
The address of the token to be bought
tokenSender_
address
The address of the sender initiating the swap
<none>
address
The address of the FXDesk fee recipient
<none>
IFrictionlessTreasuryManager
The address of the Frictionless Treasury Manager contract
<none>
IFrictionlessPermissionsManager
The address of the Frictionless Permissions Manager contract
token0_
address
the address of the first token in an exchange
token1_
address
the address of the second token in an exchange
<none>
FeeInfo
FeeInfo set for the fees associated per token in an exchange.
<none>
FeeInfo
token0_
address
the address of the token 0 in a transfer fee calculation
token1_
address
the address of the token 1 in a transfer fee calculation
<none>
bytes32
keys based on the packed encoding of the addresses of sets of tokens using the keccak256 hashing function.
<none>
bytes32
token0_
address
the address of the token 0 in a transfer fee calculation
token1_
address
the address of the token 1 in a transfer fee calculation
<none>
bytes32
generates a key based on the packed encoding of the addresses of both tokens using the keccak256 hashing function.
buyingTokensAmount_
uint256
The amount of tokens being bought
buyingTokenExchangeRate_
uint256
The exchange rate of the token being bought to the token being sold
<none>
uint256
The amount of selling tokens
tokenRecipient_
See {IFrictionlessComplianceModule}
State Variables
permissionsManager
The IFrictionlessPermissionsManager for the protocol.
complianceFactory
The IFrictionlessComplianceFactory for the protocol.
_complianceBound
the mapping of compliance modules bound.
Functions
onlyApprovedCompliance
modifier used to very that only approved compliance modules can be used.
onlyBoundCompliance
modifier used to very that only modules that are bound, can be used.
__AbstractFrictionlessComplianceModule_init
Initiatizes the compliance module
Parameters
Name
Type
Description
frictionlessPermissionsManager_
address
the address of the frictionless permissions manager
complianceFactory_
address
the address of the compliance dfactory
setPermissionsManager
Sets the instance of the IFrictionlessPermissionsManager to determine permissions for users.
Parameters
Name
Type
Description
frictionlessPermissionsManager_
address
the address of the IFrictionlessPermissionsManager contract
setComplianceFactory
Sets the instance of the IFrictionlessComplianceFactory to determine the compliance module for the protocol.
Parameters
Name
Type
Description
newComplianceFactory_
address
the address of the IFrictionlessComplianceFactory contract
bindCompliance
unbindCompliance
moduleTransferAction
moduleMintAction
moduleBurnAction
moduleCheck
isComplianceBound
isTreasury
Verifies if the specified wallet address is a PROTOCOL_TREASURY user.
Parameters
Name
Type
Description
userAddress_
address
Returns
Name
Type
Description
<none>
bool
true if the specified wallet address is a PROTOCOL_TREASURY user, otherwise false
isCustodian
Verifies if the specified wallet address is a PERMISSIONED_CUSTODIAN user.
Parameters
Name
Type
Description
userAddress_
address
Returns
Name
Type
Description
<none>
bool
true if the specified wallet address is a PERMISSIONED_CUSTODIAN user, otherwise false
isInvestor
Verifies if the specified wallet address is a PERMISSIONED_INVESTOR user.
Parameters
Name
Type
Description
userAddress_
address
Returns
Name
Type
Description
<none>
bool
true if the specified wallet address is a PERMISSIONED_INVESTOR user, otherwise false
isManager
Verifies if the specified wallet address is a PERMISSIONED_MANAGER user.
Parameters
Name
Type
Description
userAddress_
address
Returns
Name
Type
Description
<none>
bool
true if the specified wallet address is a PERMISSIONED_MANAGER user, otherwise false
isCalculatingAgent
Verifies if the specified wallet address is a PERMISSIONED_CALCULATING_AGENT user.
Parameters
Name
Type
Description
userAddress_
address
Returns
Name
Type
Description
<none>
bool
true if the specified wallet address is a PERMISSIONED_CALCULATING_AGENT user, otherwise false
isTransferAgent
Verifies if the specified wallet address is a PERMISSIONED_TRANSFER_AGENT user.
Parameters
Name
Type
Description
userAddress_
address
Returns
Name
Type
Description
<none>
bool
true if the specified wallet address is a PERMISSIONED_TRANSFER_AGENT user, otherwise false
isFundAccountant
Verifies if the specified wallet address is a PERMISSIONED_FUND_ACCOUNTANT user.
Parameters
Name
Type
Description
userAddress_
address
Returns
Name
Type
Description
<none>
bool
true if the specified wallet address is a PERMISSIONED_FUND_ACCOUNTANT user, otherwise false
isUser
Verifies if the specified wallet address is a permissioned user in the Frictionless protocol.
Parameters
Name
Type
Description
userAddress_
address
Returns
Name
Type
Description
<none>
bool
true if the specified wallet address is a permissioned user in the Frictionless protocol, otherwise false
hasClaim
verify if the userAddress is permissioned in the Frictionless protocol and has a valid claim
The IFrictionlessTreasuryManager is responsible for all token operations, minting, transferring and burning in the Frictionless protocol. The tokens and their lifecycles are defined in the public README for the Frictionless protocol at https://gitlab.com/dfyclabs/protocol/dfyclabs-tokens/-/tree/main?ref_type=heads#tokens-overview
Functions
setTokensInitData
Sets and associates the implementation authority with the associated token type
Parameters
Name
Type
Description
initDataArr_
FrictionlessTokenInitData[]
the FrictionlessTokenInitData configuration associating the implementation authority with the associated token type.
mintFundDepositForTreasury
Mints a Fund Deposit Token in the specified currency/IBAN pair. This function is invoked to create the genesis mint of the deposit token in the PROTOCOL_TREASURY.
Parameters
Name
Type
Description
depositData
IFrictionlessFundDepositToken.FFDImmutableData
the immutable deposit data for the token
treasuryAddress
address
the address of the treasury, which receives the deposit tokens
amount
uint256
the amount of tokens
Returns
Name
Type
Description
<none>
address
address of the token minted emits FrictionlessTokenMinted event throws error FrictionlessTreasuryManagerInvalidDepositData if the deposit data is invalid. requires the depositData.currency to be a 3 letter currency code requires the depositData.description to be not empty requires the depositData.IBAN to be not empty
mintDigitalSecurity
Mints a FrictionlessDigitalSecurityToken as the future dated cash distribution from the underlying FrictionlessOnChainAssetToken. This function is invoked to create the genesis mint of the deposit token in the PROTOCOL_TREASURY.
address of the token minted emits FrictionlessTokenMinted event throws error FrictionlessTreasuryManagerInvalidFDSImmutableData if the initData is invalid. requires the initData.currency to be a 3 letter currency code requires the initData.onChainAssetAddress to be non 0 address
mintOnChainAsset
Mints a FrictionlessOnChainAssetToken as the representation of the asset to be securitized, fractionalized & sold. This function is invoked to create the genesis mint of the deposit token to the PERMISSIONED_CUSTODIAN.
Parameters
Name
Type
Description
specData
IFrictionlessOnChainAssetToken.FOCASpecData
the immutable data for the token
issuanceData
IFrictionlessOnChainAssetToken.FOCAIssuanceData
the issuance data for the token
updateData
IFrictionlessOnChainAssetToken.FOCAUpdateData
the update data for the token
Returns
Name
Type
Description
<none>
address
address of the token minted emits FrictionlessTokenMinted event throws error FrictionlessTreasuryManagerInvalidFOCASpecData or FrictionlessTreasuryManagerInvalidFOCAIssuanceData if the specData or issuanceData is invalid.
mintTokenForUser
Used to increase the mint of a Frictionless token which already exists.
Parameters
Name
Type
Description
token
address
the address of the token
userAddress
address
the address to min the token to
amount
uint256
the amount of tokens to mint emits FrictionlessTokenMinted event
transferToken
Used to increase the mint of a Frictionless token which already exists.
Parameters
Name
Type
Description
token
address
the address of the token
userAddressFrom
address
the address to transfer the tokens from
userAddressTo
address
the address to transfer the tokens to
burnToken
Used to burn an amount of Frictionless token which already exists.
Parameters
Name
Type
Description
token
address
the address of the token
userAddress
address
the address to burn the tokens from
amount
uint256
the amount of tokens to burn emits FrictionlessTokenBurned event
getFundDepositToken
returns the address of the fund deposit token by currency and fundIBAN
Parameters
Name
Type
Description
currency_
string
the currency of the fund deposit token
fundIBAN_
string
the fundIBAN of the fund deposit token
Returns
Name
Type
Description
<none>
address
the address of the fund deposit token for specified currency and fundIBAN
getFundDepositTokenKey
returns fund deposit token key by currency and fundIBAN
Parameters
Name
Type
Description
currency_
string
the currency of the fund deposit token you need
fundIBAN_
string
the fundIBAN of the fund deposit token you need
Returns
Name
Type
Description
<none>
bytes32
the fund deposit token key
Events
FrictionlessTokenMinted
Event emitted when a FrictionlessFundDeposit, FrictionlessDigitalSecurity or FrictionlessOnChainAsset is minted.
FrictionlessTokenTransferred
Event emitted when a FrictionlessFundDeposit, FrictionlessDigitalSecurity or FrictionlessOnChainAsset is transferred.
FrictionlessTokenBurned
Event emitted when a FrictionlessFundDeposit, FrictionlessDigitalSecurity or FrictionlessOnChainAsset is burned.
Errors
FrictionlessIsZeroAddress
throws if specific address is zero.
FrictionlessTreasuryManagerNotAProtocolTreasury
error throw if the function caller is not a PROTOCOL_TREASURY address. Thrown during the mintFundDepositForTreasury
The Manager Contracts are the main entry points to the Frictionless protocol, they perform market functions such as permission management, treasury operations, issuance, transfer and settlement of securities, and attestations of deposits (proof-of-reserve) for the underlying of FrictionlessFundDepositTokens.
There are four main manager contracts in the Frictionless protocol, as described below.
The FrictionlessPermissionsManager defines a set of functions and events related to managing participants' permissions in the Frictionless protocol.
The interface includes an enumeration FrictionlessPermissionedUser that enumerates different participants in the Frictionless protocol, such as PROTOCOL_TREASURY, PERMISSIONED_CUSTODIAN, etc.
Only valid agents can register, add or remove users and their associated claims.
The FrictionlessTransferManager manages the transfer of tokens within the Frictionless protocol. It is also responsible for the collection of fees associated with the exchange of tokens. These fees are mapped to specific fee schedules set by managers on their respective issuances.
The FrictionlessTransferManager overview is provided in the source .
The Frictionless protocol enables GPs and Managers to collect fees on the primary issuance and secondary trades of digital securities.
The Frictionless protocol enables Investors to bilaterally trade digital securities via the FrictionlessTransferManager smart contract whilst enabling Managers to optionally collect fees on the transaction.
See mode
The Frictionless protocol enables Managers and GPs to control cash distributions, waterfalls, and capital calls without the direct action of Investors, enabling sophisticated automation via the Frictionless Markets APIs and Manager automation interface.
See mode
onlyTreasury Mode
exchangeTokens , this function will execute the exchange of tokens between two counterparties, but it is executed by the PROTOCOL_TREASURY as the transfer agent optionally collecting fees. For example, payment in FrictionlessFundDepositToken by an Investor for FricitonlessDigitalSecurityToken held by a custodian (Primary trade) or FricitonlessDigitalSecurityToken held by another Investor (secondary trade).
The exchange flow is as follows:
The PROTOCOL_ADMIN optionally sets the transfer fees for the token inbound and outbound.
The PROTOCOL_TREASURY invokes the exchangeTokens function, indicating the polarity of the transaction, such as cash for cash, cash for security, security for cash, or security for security. There are many options, but they all result in the same outcome, the compliant transfer of a Frictionless token for another Frictionless token in a single atomic transaction on-chain.
More scenarios for DvP are described in the source .
onlyCounterpart Mode
createTransferOffer confirmTransferOffer, cancelTransferOffer these functions will execute the exchange tokens in a bilateral P2P mode between two counterparties in a maker-taker mode. This mode also optionally enables the protocol to collect fees.
The exchange flow is as follows:
The PROTOCOL_ADMIN optionally sets the transfer fees for the token inbound and outbound.
Investor X invokes the createTransferOffer function, indicating the offer, such as cash for cash, cash for security, security for cash, or security for security. There are many options, but they all result in the same outcome, the compliant transfer of a Frictionless token for another Frictionless token in a single atomic transaction on-chain.
Investor Y can accept the offer by invoking the
The FrictionlessTreasuryManager manages the minting, transfer, and burning of various within the Frictionless protocol
Token Minting and Management:
The contract provides functions to mint different types of tokens within the Frictionless protocol, including Fund Deposit Tokens (mintFundDepositForTreasury), Digital Security Tokens (mintDigitalSecurity), and On-Chain Asset Tokens (mintOnChainAsset).
The PROTOCOL_ADMIN is the only role permissioned to initially mint any Frictionless tokens, thereafter valid agents such as the PROTOCOL_TREASURY are permitted to increase supply (mint to address), transfer and burn Frictionless tokens.
The FrictionlessAttestationManager responsible for providing attestations of the balances held in the underlying funding account for each FrictionlessFundDepositToken. The attestation is provided and signed by an independent 3rd party, known as PERMISSIONED_FUND_ACCOUNTANT in the Frictionless protocol.
Attestations are proof of balances in each currency on a regular basis for example, daily or hourly, the attestation data is based on the following snapshot of the currency account underpinning the FrictionlessFundDepositToken.
ATTESTATION FIELD
ATTESTATION COMMENT
The attestation workflows are described in the source .
function setTokensInitData(FrictionlessTokenInitData[] calldata initDataArr_) external;
the address of the protocol user, which receives the digital security tokens
custodianAddress
address
the address of the protocol custodian, which receives the FrictionlessOnChainAssetToken
amount
uint256
the amount of tokens to mint emits FrictionlessTokenTransferred event
The transfer is enacted using the ERC-3643-compliant token transfer
IToken.forcedTransfer
.
confirmTransferOffer
function, ensuring the ERC-3643-compliant token transfer using
IToken.transferFrom
.
Tokens are associated with compliance contracts, and their minting is subject to specific conditions, roles, and permissions.
Token Transfer and Burning:
The contract allows for the transfer and burning of tokens through functions like transferToken and burnToken. These actions are performed by an agent with the necessary permissions.
Fund Deposit Token Management:
The contract keeps track of existing Fund Deposit Tokens using a mapping _existingFundDepositTokens. It prevents the creation of duplicate Fund Deposit Tokens for the same currency and fund IBAN.
LAST_TX_COUNTERPARTY_ID
The ID of the counterparty in the last transaction on the account
LAST_TX_TIMESTAMP
The timestamp (same format as REPORT_END_DATE) in the last transaction on the account
LAST_TX_AMOUNT
The amount of the the last transaction on the account, A credit transaction is positive and a debit transaction is negative
CASH_IBAN
The IBAN of the cash account
CURRENCY
The 3-letter currency code of the cash account
REPORT_START_DATE
The start of this report, for example, yesterday at 6AM
REPORT_END_DATE
The end of this report, for example, today at 6AM
CASH_BALANCE
The actual balance on the account as of REPORT_END_DATEfor example, today 6AM
Interface defining the frictionless conversion and atomic swapping of ERC-20 tokens for FrictionlessFundDepositToken on the Frictionless protocol. The conversion of tokens is considered frictionless as the protocol does not impose any fee structures on the conversion itself.
Functions
pause
See {PausableUpgradeable-_pause}
unpause
See {PausableUpgradeable-_unpause}
setConvertTokensFees
Set the conversion fees for the token pair. The fees can be any combination of zero (0%) or upto 10000 bps (100%) on any directional transfer. Fees can only be set by the Owner (PROTOCOL_ADMIN).
Parameters
Name
Type
Description
setConvertTokensFee
Set the conversion fees for the token pair using the tokenFeeKey_. The fees can be any combination of zero (0%) or upto 10000 bps (100%) on any directional transfer. Fees can only be set by the Owner (PROTOCOL_ADMIN).
Parameters
Name
Type
Description
removeFrictionlessTokensConvertInfo
Removes the conversion fees for the token pair using the tokenFeeKey_. Fees can only be set by the Owner (PROTOCOL_ADMIN).
Parameters
Name
Type
Description
addFrictionlessTokensConvertInfo
Sets the mapping for the convertible tokens in the contract, calling this will add a new conversion pair to the contract.
Parameters
Name
Type
Description
convertFromERC20
Converts from an ERC20 token to a FrictionlessFundDepositToken, using the safe precision conversion. The ERC20 token is transferred to configured treasuryAddress in the conversion and the minted FrictionlessFundDepositToken is sent to the msg.sender
Parameters
Name
Type
Description
convertFromERC20
Converts from an ERC20 token to a FrictionlessFundDepositToken, using the safe precision conversion. The ERC20 token is transferred to configured treasuryAddress in the conversion and the minted FrictionlessFundDepositToken is sent to the convertedTokensRecipient_
Parameters
Name
Type
Description
Returns
Name
Type
Description
convertToERC20
Converts to an ERC20 token from a FrictionlessFundDepositToken, using the safe precision conversion. The FrictionlessFundDepositToken is burned in the conversion and the ERC20 is sent to the msg.sender from the treasuryAddress.
Parameters
Name
Type
Description
Returns
Name
Type
Description
convertToERC20
Converts to an ERC20 token from a FrictionlessFundDepositToken, using the safe precision conversion. The FrictionlessFundDepositToken is burned in the conversion and the ERC20 is sent to the convertedTokensRecipient_ from the treasuryAddress.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getConvertTokenInfo
Returns the FrictionlessTokensConvertInfo for the given conversion key
Parameters
Name
Type
Description
Returns
Name
Type
Description
getConvertTokenKeysByToken
Returns the conversion keys for the given tokenAddr_
Parameters
Name
Type
Description
Returns
Name
Type
Description
getConvertTokenKeysCountByToken
Returns the count of conversion keys for the given tokenAddr_
Parameters
Name
Type
Description
Returns
Name
Type
Description
getConvertTokenInfosByToken
Returns the FrictionlessTokensConvertInfo for the given tokenAddr_
Parameters
Name
Type
Description
Returns
Name
Type
Description
isTokenSupported
Returns true if the token specified by the tokenAddr_ has been registered as a valid convertible pair.
Parameters
Name
Type
Description
Returns
Name
Type
Description
isTokenPairSupported
Returns true if the token pair specified have been registered as a valid convertible pair.
Parameters
Name
Type
Description
Returns
Name
Type
Description
isConvertTokenKeySupported
Returns true if the conversion key is supported.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getConvertTokensKey
Returns the conversion key for the given token pair.
Parameters
Name
Type
Description
Returns
Name
Type
Description
Events
FrictionlessTokensConverted
Event emitted when a successful conversion occurs between an ERC20 and a FrictionlessFuncDepositToken.
thrown during a convert to/from an ERC20 if the conversion is attempted for the same token
FrictionlessERC20ConverterManagerZeroAddress
thrown if the IFrictionlessERC20ConverterManager is configured as a zero address
Structs
FrictionlessTokensConvertInfo
Struct to represent the conversion between an ERC20 token and a FrictionlessFundDepositToken on the Frictionless protocol
uint256
the amount of tokens to convert
uint256
the amount of tokens to convert
erc20Token_
address
the address of the ERC20 token.
fundDepositToken_
address
the address of the FundDeposit token.
feeInfo_
FeeInfo
The fees associated with the conversion of the token pair. throws FrictionlessERC20ConverterManagerUnsupportedPair if the token pair is not valid throws AbstractFeeModuleInvalidFeeRecipient if the feeRecipientAddr is a zero address throws AbstractFeeModuleInvalidFee if the feeInBps is not in the valid range (ZERO_FEES_IN_BPS to MAX_FEES_IN_BPS) emits FrictionlessTokenFeeSet upon completion of the setting of the fee info for the token in either set of fees
tokenFeeKey_
bytes32
the tokenFeeKey as determined getConvertTokensKey
feeInfo_
FeeInfo
The fees associated with the conversion of the token pair. throws FrictionlessERC20ConverterManagerUnsupportedPair if the token pair is not valid throws AbstractFeeModuleInvalidFeeRecipient if the feeRecipientAddr is a zero address throws AbstractFeeModuleInvalidFee if the feeInBps is not in the valid range (ZERO_FEES_IN_BPS to MAX_FEES_IN_BPS) emits FrictionlessTokenFeeSet upon completion of the setting of the fee info for the token in either set of fees
erc20Token_
address
the address of the ERC20 token.
fundDepositToken_
address
the address of the FundDeposit token.
tokensConvertInfoArr_
FrictionlessTokensConvertInfo[]
the array of token conversions to set. throws FrictionlessERC20ConverterManagerInvalidTokenConvertInfo if the tokensConvertInfoArr_ contains zero addresses throws FrictionlessERC20ConverterManagerUnableToUpdateConvertInfo if the tokensConvertInfoArr_ cannot be updated
erc20Token_
address
the address of the ERC20 token to convert from, which must exist in a FrictionlessTokensConvertInfo in order to succeed.
fundDepositToken_
address
the address of the FundDeposit token to convert to, which must exist in a FrictionlessTokensConvertInfo in order to succeed.
erc20TokensAmount_
uint256
the amount of tokens to convert throws FrictionlessERC20ConverterManagerInvalidTokenType if the tokenAddr_ is not a configured convertible erc20Token throw FrictionlessERC20ConverterManagerInvalidTokensAmountAfterConversion if the conversion resolves to zero Emits the event FrictionlessTokensConverted detailing the full convertibility
erc20Token_
address
the address of the ERC20 token to convert from, which must exist in a FrictionlessTokensConvertInfo in order to succeed.
fundDepositToken_
address
the address of the FundDeposit token to convert to, which must exist in a FrictionlessTokensConvertInfo in order to succeed.
convertedTokensRecipient_
address
the destination of the converted FrictionlessFundDepositToken
<none>
uint256
the amount of FrictionlessFundDepositToken converted throws FrictionlessERC20ConverterManagerInvalidTokenType if the tokenAddr_ is not a configured convertible erc20Token throw FrictionlessERC20ConverterManagerInvalidTokensAmountAfterConversion if the conversion resolves to zero Emits the event FrictionlessTokensConverted detailing the full convertibility
erc20Token_
address
fundDepositToken_
address
the address of the FrictionlessFundDepositToken token to convert from, which must exist in a FrictionlessTokensConvertInfo in order to succeed.
fundDepositTokensAmount_
uint256
the amount of tokens to convert
<none>
uint256
the amount of ERC20 converted throws FrictionlessERC20ConverterManagerInvalidTokenType if the tokenAddr_ is not a configured convertible fundDepositToken throw FrictionlessERC20ConverterManagerInvalidTokensAmountAfterConversion if the conversion resolves to zero Emits the event FrictionlessTokensConverted detailing the full convertibility
erc20Token_
address
fundDepositToken_
address
the address of the FrictionlessFundDepositToken token to convert from, which must exist in a FrictionlessTokensConvertInfo in order to succeed.
convertedTokensRecipient_
address
the destination of the converted ERC20 token
<none>
uint256
the amount of ERC20 converted throws FrictionlessERC20ConverterManagerInvalidTokenType if the tokenAddr_ is not a configured convertible fundDepositToken throw FrictionlessERC20ConverterManagerInvalidTokensAmountAfterConversion if the conversion resolves to zero Emits the event FrictionlessTokensConverted detailing the full convertibility
convertInfoKey_
bytes32
the address of the token to validate.
<none>
FrictionlessTokensConvertInfo
the FrictionlessTokensConvertInfo for the given conversion key
tokenAddr_
address
the address of the token to validate.
<none>
bytes32[]
the conversion keys arr for the given tokenAddr_
tokenAddr_
address
the address of the token to validate.
<none>
uint256
the count of conversion keys arr for the given tokenAddr_
tokenAddr_
address
the address of the token to validate.
<none>
FrictionlessTokensConvertInfo[]
the FrictionlessTokensConvertInfo for the given tokenAddr_
tokenAddr_
address
the address of the token to validate.
<none>
bool
true if the token specified by the tokenAddr_ has been registered as a valid convertible pair, otherwise false
erc20Token_
address
the address of the ERC20 token.
fundDepositToken_
address
the address of the FundDeposit token.
<none>
bool
true if the token pair specified have been registered as a valid convertible pair, otherwise false
convertTokenKey_
bytes32
the conversion key as defined by getConvertTokensKey
<none>
bool
true if Returns true if the conversion key is supported, otherwise false
token0_
address
the first token in the convertible pair
token1_
address
the second token in the convertible pair
<none>
bytes32
the conversion key for the given token pair throws FrictionlessERC20ConverterManagerIdenticalAddresses if both tokens are identical throws FrictionlessERC20ConverterManagerZeroAddress if the tokens are a zero address
erc20TokensAmount_
fundDepositTokensAmount_
function pause() external;
function unpause() external;
function setConvertTokensFees(address erc20Token_, address fundDepositToken_, FeeInfo calldata feeInfo_) external;
function setConvertTokensFee(bytes32 tokenFeeKey_, FeeInfo calldata feeInfo_) external;
function removeFrictionlessTokensConvertInfo(address erc20Token_, address fundDepositToken_) external;
function addFrictionlessTokensConvertInfo(FrictionlessTokensConvertInfo[] calldata tokensConvertInfoArr_) external;
function convertFromERC20(address erc20Token_, address fundDepositToken_, uint256 erc20TokensAmount_)
external
returns (uint256);
The IFrictionlessTransferManager is responsible for the management of the various transfer methodologies, fees processing, and defined control paradigm for DvP for all tokens in the Frictionless protocol. The tokens and their lifecycles are defined in the public README for the Frictionless protocol at https://gitlab.com/dfyclabs/protocol/dfyclabs-tokens/-/blob/main/README.md?ref_type=heads#funds-flows
Functions
updateMinRedeemAmount
Set a minimum redemption amount, to ensure there is meaningful settlement amounts, generally this is used to ensure FIAT transfers are above a minimum banking threshold, such as 1 USD.
Parameters
Name
Type
Description
newMinRedeemAmount_
uint256
the minimum redemption amount, if not reached , typically throws FrictionlessTransferManagerRedeemAmountIsLessThanMinimum
setTransferFees
Set the transfer fees for the exchange/settlement of a token pair. The fees can be any combination of zero (0%) or upto 10000 bps (100%) on any directional transfer. Fees can only be set by the Owner (PROTOCOL_ADMIN).
Parameters
Name
Type
Description
token0FeeInfo_
TokenFeeInfo
The fees associated with the transfer of token0 (first token) in the exchange/settlement of the token pair.
token1FeeInfo_
TokenFeeInfo
The fees associated with the transfer of token1 (second token) in the exchange/settlement of the token pair. throws FrictionlessTransferManagerInvalidTokenAddresses if the token addresses are invalid. throws AbstractFeeModuleInvalidFeeRecipient if the feeRecipientAddr is a zero address throws AbstractFeeModuleInvalidFee if the feeInBps is not in the valid range (ZERO_FEES_IN_BPS to MAX_FEES_IN_BPS) emits FrictionlessTokenFeeSet upon completion of the setting of the fee info for the token in either set of fees
setTokenFee
Set the fee associated with the transfer of a Token and manages the mapping of the key to this set of Fees. Can only be set by the Owner (PROTOCOL_ADMIN).
Parameters
Name
Type
Description
tokenFeeKey_
bytes32
the key, generated by the function getTokenFeeKey, which is used to map a specific transfer polarity for tokens.
tokenFeeInfo_
TokenFeeInfo
The fees associated with the transfer of token, used in the calculation and disbursement of fees during exchange/settlement of a token pair. throws FrictionlessTransferManagerInvalidTokenAddresses if the token addresses are invalid. throws AbstractFeeModuleInvalidFeeRecipient if the feeRecipientAddr is a zero address throws AbstractFeeModuleInvalidFee if the feeInBps is not in the valid range (ZERO_FEES_IN_BPS to MAX_FEES_IN_BPS) emits FrictionlessTokenFeeSet upon completion of the setting of the fee info for the token
exchangeTokens
Executes a token pair exchange. This function can only be invoked by the PROTOCOL_TREASURY
Parameters
Name
Type
Description
token0TransferData_
TokenTransferData
the transfer data for the first token in the exchange
token1TransferData_
TokenTransferData
the transfer data for the second token in the exchange throws FrictionlessTransferManagerNotEnoughTokens if the balance of any of the tokens held by any users in the transfer is below the transfer amount throws FrictionlessTransferManagerInvalidTokenAddresses if any of the token addresses are zero. throws FrictionlessTransferManagerZeroAmount if any of the token amounts are zero throws FrictionlessTransferManagerInvalidTokenSenderAddresses if the expectedToken0Sender_ is not the same as the token0TransferData_.tokenSender throws FrictionlessTransferManagerInvalidTokenSenderAddresses if the token1TransferData_.tokenSender is a zero address emits FrictionlessTokensExchanged upon successful exchange.
createTransferOffer
Initiates/Creates a transferOffer between a token pair exchange. Setting the transfer status to PENDING for state management of the overall transfer. This function generates a transferOfferId_ which is returned so invokers of the function can perform further functions such as confirmTransferOffer or cancelOffer.
Parameters
Name
Type
Description
token0TransferData_
TokenTransferData
the transfer data for the first token in the exchange
token1TransferData_
TokenTransferData
the transfer data for the second token in the exchange
Returns
Name
Type
Description
<none>
uint256
transferOfferId_ representing the stored transfer in this contract for future operations such as confirmTransferOffer or cancelOffer. throws FrictionlessTransferManagerNotEnoughTokens if the balance of any of the tokens held by any users in the transfer is below the transfer amount throws FrictionlessTransferManagerInvalidTokenAddresses if any of the token addresses are zero. throws FrictionlessTransferManagerZeroAmount if any of the token amounts are zero throws FrictionlessTransferManagerInvalidTokenSenderAddresses if the expectedToken0Sender_ is not the same as the token0TransferData_.tokenSender throws FrictionlessTransferManagerInvalidTokenSenderAddresses if the token1TransferData_.tokenSender is a zero address emits FrictionlessTransferOfferCreated upon successful offer created.
redeemTokens
Redeem/Burn an amount for tokens for the specified tokenAddr_ and msg.sender
Parameters
Name
Type
Description
tokenAddr_
address
the address of the token
redeemAmount_
uint256
the amount of the token to burn (redeem) throws FrictionlessTransferManagerZeroAddress if the token address or the msg.sender is a zero address throws FrictionlessTransferManagerZeroAmount if the redeemAmount_ is zero throws FrictionlessTransferManagerNotEnoughTokens if the balance of a user for a given token is below the redeemAmount_ emits FrictionlessTokensRedeemed when the burn has occurred
redeemERC20Tokens
Redeem/Burn an amount for tokens for the specified ERC20 tokenAddr_ and msg.sender, this will convert the ERC20 token to a FrictionlessFundDepositToken first, then redeem See {IFrictionlessERC20ConverterManager-isTokenSupported} {IFrictionlessERC20ConverterManager-convertFromERC20}
Parameters
Name
Type
Description
erc20Token_
address
the address of the ERC20 token
fundDepositToken_
address
the address of the FundDeposit token
tokenRedeemAmount_
uint256
the amount of the token to convert & burn (redeem) throws FrictionlessTransferManagerZeroAddress if the token address or the msg.sender is a zero address throws FrictionlessTransferManagerZeroAmount if the tokenRedeemAmount_ is zero throws FrictionlessTransferManagerNotEnoughTokens if the balance of a user for a given token is below the tokenRedeemAmount_ throws FrictionlessTransferManagerInvalidERC20TokenForRedeem if the tokenAddr_ is noy a valid convertible ERC20 token emits FrictionlessTokensRedeemed when the burn has occurred
redeemTokensFrom
Redeem/Burn an amount for tokens for the specified tokenAddr_ and userAddr_. This function can only be invoked by the PROTOCOL_TREASURY
Parameters
Name
Type
Description
tokenAddr_
address
the address of the token
userAddr_
address
the address of the holder of the token
redeemAmount_
uint256
the amount of the token to burn (redeem) throws FrictionlessTransferManagerZeroAddress if the token address or the userAddr_ is a zero address throws FrictionlessTransferManagerZeroAmount if the redeemAmount_ is zero throws FrictionlessTransferManagerNotEnoughTokens if the balance of a user for a given token is below the redeemAmount_ emits FrictionlessTokensRedeemed when the burn has occurred
redeemERC20TokensFrom
Redeem/Burn an amount for tokens for the specified ERC20 tokenAddr_ and userAddr_. This will convert the ERC20 token to a FrictionlessFundDepositToken first, then reedem. This function can only be invoked by the PROTOCOL_TREASURY See {IFrictionlessERC20ConverterManager-isTokenSupported} {IFrictionlessERC20ConverterManager-convertFromERC20}
Parameters
Name
Type
Description
erc20Token_
address
the address of the ERC20 token
fundDepositToken_
address
the address of the FundDeposit token
userAddr_
address
the address of the holder of the token
confirmTransferOffer
Confirms and processes the transfer for the respective transferOfferId_, which results int he compliant token transfers under ERC-3643 specification to occur.
Parameters
Name
Type
Description
transferOfferId_
uint256
the id of the transfer returned/emitted in the function createTransferOffer Requires the transfer status is TransferStatuses.PENDING throws FrictionlessTransferManagerInvalidTransferStatus if the transfer status is NOT TransferStatuses.PENDING throws FrictionlessTransferManagerNotEnoughPermissions If the msg.sender is not the tokenSender of the second token in the exchange or if the msg.sender is not a valid TREX Agent of either toekns in the exchange. emits FrictionlessTransferOfferConfirmed upon successful completion of the transfers.
cancelTransferOffer
Cancels a transfer for the given transferOfferId_, which results in the transfer status being set to TransferStatuses.CANCELED and the relevant FrictionlessTransferOfferCanceled being emitted.
Parameters
Name
Type
Description
transferOfferId_
uint256
the generated transferOfferId_ used to store the state of transfers in the contract. requires the Transfer to be in a PENDING state. throws FrictionlessTransferManagerInvalidTransferStatus if the transfer status is NOT TransferStatuses.PENDING throws FrictionlessTransferManagerNotEnoughPermissions If the msg.sender is not the tokenSender of the second token in the exchange or if the msg.sender is not a valid TREX Agent of either tokens in the exchange.
nextTransferOfferId
Generates the next transferOfferId in the smart contract, used to store state of a transfer.
Returns
Name
Type
Description
<none>
uint256
the next transferOfferId in the smart contract, used to store state of a transfer.
minRedeemAmount
Get the minimum redemption amount configured
Returns
Name
Type
Description
<none>
uint256
minimum redemption amount, to ensure there is meaningful settlement amounts, generally this is used to ensure FIAT transfers are above a minimum banking threshold, such as 1 USD.
getTransferData
Returns the transfer data stored for the given transferOfferId_
Parameters
Name
Type
Description
transferOfferId_
uint256
the generated transferOfferId_ used to store the state of transfers in the contract
Returns
Name
Type
Description
<none>
TransferData
TransferData, the transfer data for the given transferOfferId_
getTransferFeesInfo
get the tokenFeeInfo set for the fees associated per token in an exchange.
Parameters
Name
Type
Description
token0_
address
the address of the first token in an exchange
token1_
address
the address of the second token in an exchange
Returns
Name
Type
Description
<none>
FeeInfo
FeeInfo set for the fees associated per token in an exchange.
<none>
FeeInfo
getTransferFeeKeys
Generates keys based on the packed encoding of the addresses of sets of tokens using the keccak256 hashing function. Used to store tokenFees in mappings.
Parameters
Name
Type
Description
token0_
address
the address of the token 0 in a transfer fee calculation
token1_
address
the address of the token 1 in a transfer fee calculation
Returns
Name
Type
Description
<none>
bytes32
keys based on the packed encoding of the addresses of sets of tokens using the keccak256 hashing function.
<none>
bytes32
getTokenFeeKey
Generates a key based on the packed encoding of the addresses of both tokens using the keccak256 hashing function. Used to store tokenFees in mappings.
Parameters
Name
Type
Description
token0_
address
the address of the token 0 in a transfer fee calculation
token1_
address
the address of the token 1 in a transfer fee calculation
Returns
Name
Type
Description
<none>
bytes32
generates a key based on the packed encoding of the addresses of both tokens using the keccak256 hashing function.
Events
FrictionlessTransferOfferCreated
Event emitted during createTransferOffer
FrictionlessTransferOfferConfirmed
Event emitted during confirmTransferOffer
FrictionlessTransferOfferCanceled
Event emitted during cancelOffer
FrictionlessTokensExchanged
Event emitted during exchangeTokens
FrictionlessTokensRedeemed
Event emitted during redeemTokens and redeemTokensFrom
Errors
FrictionlessTransferManagerInvalidTokenAddresses
error thrown during setTransferFees, setTransferFees, exchangeTokens or createTransferOffer if any of the token addresses are zero.
error thrown when the redemption amount is below the configured minimum, during redeemTokens or redeemERC20Tokens
FrictionlessTransferManagerNotEnoughTokens
error thrown during exchangeTokens, createTransferOffer, redeemTokens or redeemTokensFrom if the balance of any of the tokens held by any users in the transfer is below the transfer amount
FrictionlessTransferManagerInvalidTransferStatus
error thrown during confirmTransferOffer or cancelOffer if the transfer status expectedStatus does not match the actualStatus
FrictionlessTransferManagerNotEnoughPermissions
error thrown during createTransferOffer or confirmTransferOffer if any of the msg.sender is not an Agent of the tokens in the transfer.
Structs
TokenFeeInfo
TokenFeeInfo represents the fee (zero or otherwise) that is associated with the transfer of a token in the Transfer Manager exchange.
TokenTransferData
TokenTransferData represents the data set in a transfer of a token
TransferData
TransferData represents a maker/taker model of transfer, where 1 token is exchanged for another
the amount of the token to convert and burn (redeem) throws FrictionlessTransferManagerZeroAddress if the token address or the userAddr_ is a zero address throws FrictionlessTransferManagerZeroAmount if the tokenRedeemAmount_ is zero throws FrictionlessTransferManagerNotEnoughTokens if the balance of a user for a given token is below the tokenRedeemAmount_ throws FrictionlessTransferManagerInvalidERC20TokenForRedeem if the tokenAddr_ is noy a valid convertible ERC20 token emits FrictionlessTokensRedeemed when the burn has occurred
The IFrictionlessAttestationManager See the flow and description of the attestation workflow in the diagram at https://gitlab.com/dfyclabs/protocol/dfyclabs-tokens/-/raw/main/docs/img/frictionless-fund-deposit-flow-attestation.png
Functions
updateAttestationToken
Update the token address of the FrictionlessFundDepositToken for the currency_ and iban_ pair.
Parameters
Name
Type
Description
confirmAttestation
Confirm the attestation by signing the signature, this is the proof of the attestation by the PERMISSIONED_FUND_ACCOUNTANT
Parameters
Name
Type
Description
minBalance
Get the minimum balance amount configured, for which an attestation can be run. If the balance of the attestation is below the value configured, the error will be thrown. The minimum allowed is 10_000 or 0.01
Returns
Name
Type
Description
minWindow
Get minimum time (reportEnd - reportStart) in blocktime for which an attestation can be run. Typically this is 1 hour, and dependent on the availability of transaction data in the underlying fund account as specified by the IBAN. The minimum allowed is 300 seconds.
Returns
Name
Type
Description
maxWindow
Get maximum time (reportEnd - reportStart) in blocktime for which an attestation can be run. Typically this is 30 days, aligned with the reporting as per regulation for the underlying fund and issuer of the deposit token. The maximum allowed is 365 days.
Returns
Name
Type
Description
getAccountAttestationDataKeys
Retrieves the keys of attestation data associated with a specific account identified by IBAN and currency.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getAccountLastAttestationData
Retrieves the last attestation data associated with a specific account identified by IBAN and currency.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getAccountLastAttestationDataKey
Retrieves the key of the last attestation data associated with a specific account identified by IBAN and currency.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getAttestationData
Retrieves attestation data by the attestation data key.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getTokenAddress
Get the valid FrictionlessFundDepositToken for the currency_ and iban_ pair.
Parameters
Name
Type
Description
Returns
Name
Type
Description
getAttestationDataHash
Mint a new attestation, it returns hash of attestation data to sign by the PERMISSIONED_FUND_ACCOUNTANT
Parameters
Name
Type
Description
Returns
Name
Type
Description
getAccountAttestationKey
Retrieves the attestation data key associated with a specific account identified by currency and IBAN.
Parameters
Name
Type
Description
Returns
Name
Type
Description
Events
FrictionlessFundDepositAttestationTokenUpdated
Emitted when the FrictionlessFundDepositToken is updated in the IFrictionlessAttestationManager.
FrictionlessFundDepositAttestationConfirmed
Event emitted upon the confirmation of a FrictionlessFundDepositToken in the IFrictionlessAttestationManager
thrown if the attestation cannot be confirmed, meaning the signed attestation cannot be verified.
Structs
AttestationData
struct to hold attestation data, which is designed to provide the most recent attestation of balance and verified last transaction in an attestation window.
AccountAttestationData
struct to hold account attestation data
tokenAddress_
address
the address of deposit FrictionlessFundDepositToken
iban_
string
the IBAN associated with the FrictionlessFundDepositToken
currency_
string
the currency associated with the FrictionlessFundDepositToken throws FrictionlessAttestationManagerTokenZeroAddress if tokenAddress_ address is a zero address emits FrictionlessFundDepositAttestationTokenUpdated upon successful updating
attestationData_
AttestationData
attestation data to sign
sig_
bytes
the signature to sign by the PERMISSIONED_FUND_ACCOUNTANT throws FrictionlessAttestationManagerNotEnoughPermissions if the msg.sender does not have the role PERMISSIONED_FUND_ACCOUNTANT throws FrictionlessAttestationManagerInvalidAttestation if the attestation cannot be confirmed, meaning the signed attestation cannot be verified. emits FrictionlessFundDepositAttestationConfirmed upon successful signing
<none>
uint256
minimum attestation balance.
<none>
uint256
minimum attestation window.
<none>
uint256
maximum attestation window.
iban_
string
the IBAN associated with the FrictionlessFundDepositToken
currency_
string
the currency associated with the FrictionlessFundDepositToken
<none>
bytes32[]
the array of bytes32 attestation data keys associated with the account.
iban_
string
the IBAN associated with the FrictionlessFundDepositToken
currency_
string
the currency associated with the FrictionlessFundDepositToken
<none>
AttestationData
the AttestationData struct representing the last attestation data associated with the account.
iban_
string
the IBAN associated with the FrictionlessFundDepositToken
currency_
string
the currency associated with the FrictionlessFundDepositToken
<none>
bytes32
the last attestation data key associated with the account.
attestationDataKey_
bytes32
the key identifying the attestation data
<none>
AttestationData
the AttestationData struct representing the attestation data associated with the given key.
iban_
string
the IBAN associated with the FrictionlessFundDepositToken
currency_
string
the currency associated with the FrictionlessFundDepositToken
<none>
address
the address of the valid FrictionlessFundDepositToken for the currency_ and iban_ pair
attestationData_
AttestationData
the complete set of attestation data to for the PERMISSIONED_FUND_ACCOUNTANT to certify/sign.
<none>
bytes32
a hash of the attestationData which will be signed to confirm the attestation
currency_
string
the currency associated with the FrictionlessFundDepositToken
iban_
string
the IBAN associated with the FrictionlessFundDepositToken
<none>
bytes32
the accound attestation key.
function updateAttestationToken(address tokenAddress_, string calldata iban_, string calldata currency_) external;
function confirmAttestation(AttestationData calldata attestationData_, bytes calldata sig_) external;
function minBalance() external view returns (uint256);
function minWindow() external view returns (uint256);
function maxWindow() external view returns (uint256);