Restricted Swap
Overview
RestrictedSwap provides a secure means of swapping tokens between known holders of the primary Restricted token and any payment ERC-20 tokens (ie USDC, DAI, etc).
Note: Restricted Swap is not intended between two Restricted tokens. Rather, it is intended as a purchase of Restricted tokens using ERC-20 tokens (AKA payment token or quote token). This is enforced in the Restricted Swap contract itself, by preventing ERC-1404 compatible tokens (checked via ERC-165 interface support) from being used as payment. However, other types of Restricted tokens may not explicitly support the ERC-1404 interface and thus cannot be checked programmatically; therefore, this functionality should be used with caution and payment token types should always be verified first.
Usage
How It Works
As a prerequisite, users of the swap functionality are assumed to have passed any necessary off-chain AML/KYC and deemed valid holders. Contracts are also assumed to have been configured properly with admin-granted roles and transfer restrictions in place.
Configuring a Purchase of Restricted Token
As a holder (Buyer) of an ERC-20 payment token (ie USDC, DAI, etc), one can configure a purchase order for a specified amount of Restricted token with a known party (Seller). Here is an example involving USDC:
Buyermust know in advance specifically how much Restricted token they'd like to receive, how much USDC they are willing to pay, and theSelleron the other end.Buyermust approve the Swap contract itself to handle their USDC in the purchase amount required.Buyerthen configures an open purchase order by callingconfigureBuywith the following parameters. A Swap ID is emitted in an event.- amount of Restricted token desired
- address of
Seller - amount of payment token (USDC) willing to swap
- address of payment token contract
Sellermust approve the Swap contract itself to handle their Restricted token in the sell amount required by the configured swap.Sellercan complete this order by callingcompleteSwapWithRestrictedTokenwith the emitted Swap ID.
When transfer restrictions are validated between Buyer and Seller, the swap is completed and assets are actually transferred between transacting parties.
Note: Role checks (e.g., pausing, admin-only operations) are resolved through the pre-deployed AccessControl contract referenced by the Restricted token and ancillary contracts.
Configuring a Sale of Restricted Token
As a holder of the Restricted token, one can also configure a sell order for a specified amount of desired payment ERC-20 token. It is extremely similar to the example above, except terms of the sale must be specified in advance. Here is an example involving USDC:
Sellermust know in advance specifically how much Restricted token they'd like to sell, how much USDC they require, and theBuyeron the other end.Sellermust approve the Swap contract itself to handle their Restricted token in the sell amount desired.Sellerthen configures an open sell order by callingconfigureSellwith the following parameters. A Swap ID is emitted in an event.- amount of Restricted token to sell
- address of
Buyer - amount of payment token (USDC) required
- address of payment token contract
Buyermust approve the Swap contract itself to handle their USDC in the amount specified by the configured swap.Buyercan complete this order by callingcompleteSwapWithQuoteTokenwith the emitted Swap ID.
When transfer restrictions are validated between Buyer and Seller, the swap is completed and assets are actually transferred between transacting parties.
API Reference
Constructor
constructor(address restrictedLockupTokenAddress_, address trustedForwarder_, address accessControl_)
Initializes the RestrictedSwap contract with configuration parameters.
Parameters:
restrictedLockupTokenAddress_(address): The RestrictedLockupToken contract addresstrustedForwarder_(address): ERC-2771 trusted forwarder address for meta-transactionsaccessControl_(address): AccessControl contract address for role management
Requirements:
- All addresses must be non-zero
- Access control address must be valid
Administrative Functions
pause(bool isPaused_)
Pauses or unpauses the contract functionality.
Parameters:
isPaused_(bool): True to pause, false to unpause
Requirements:
- Caller must have CONTRACT_ADMIN_ROLE or TRANSFER_ADMIN_ROLE
Emits: Paused(account) or Unpaused(account)
Swap Configuration Functions
configureSell(uint256 restrictedTokenAmount, address quoteToken, address quoteTokenSender, uint256 quoteTokenAmount)
Configures a sell order for restricted tokens in exchange for quote tokens.
Parameters:
restrictedTokenAmount(uint256): Amount of restricted tokens to sellquoteToken(address): Address of the quote token (ERC-20) to receivequoteTokenSender(address): Address that will provide the quote tokensquoteTokenAmount(uint256): Amount of quote tokens to receive
Requirements:
- Contract must not be paused
- Quote token sender must not be zero address
- Quote token must not be zero address
- Caller must have sufficient restricted token allowance for this contract
- Quote token must not support ERC-1404 interface (to prevent restricted token swaps)
Emits: SwapConfigured(swapNumber, restrictedTokenSender, restrictedTokenAmount, quoteToken, quoteTokenSender, quoteTokenAmount)
configureBuy(uint256 restrictedTokenAmount, address restrictedTokenSender, address quoteToken, uint256 quoteTokenAmount)
Configures a buy order for restricted tokens using quote tokens.
Parameters:
restrictedTokenAmount(uint256): Amount of restricted tokens to buyrestrictedTokenSender(address): Address that will provide the restricted tokensquoteToken(address): Address of the quote token (ERC-20) to pay withquoteTokenAmount(uint256): Amount of quote tokens to pay
Requirements:
- Contract must not be paused
- Restricted token sender must not be zero address
- Quote token must not be zero address
- Caller must have sufficient quote token balance
- Caller must have sufficient quote token allowance for this contract
- Quote token must not support ERC-1404 interface
Emits: SwapConfigured(swapNumber, restrictedTokenSender, restrictedTokenAmount, quoteToken, quoteTokenSender, quoteTokenAmount)
Swap Execution Functions
completeSwapWithQuoteToken(uint256 swapNumber_)
Completes a swap by providing quote tokens (used by quote token sender in sell-configured swaps).
Parameters:
swapNumber_(uint256): The swap number to complete
Requirements:
- Contract must not be paused
- Swap must not be canceled or already completed
- Caller must be the quote token sender for this swap
- Swap status must be SellConfigured
- Quote token sender must have sufficient quote token balance
- Restricted token sender must have sufficient restricted token balance
- Transfer restrictions must be satisfied between parties
Emits: SwapComplete(swapNumber, restrictedTokenSender, restrictedTokenAmount, quoteTokenSender, quoteToken, quoteTokenAmount)
completeSwapWithRestrictedToken(uint256 swapNumber_)
Completes a swap by providing restricted tokens (used by restricted token sender in buy-configured swaps).
Parameters:
swapNumber_(uint256): The swap number to complete
Requirements:
- Contract must not be paused
- Swap must not be canceled or already completed
- Caller must be the restricted token sender for this swap
- Swap status must be BuyConfigured
- Quote token sender must have sufficient quote token balance
- Restricted token sender must have sufficient restricted token balance
- Transfer restrictions must be satisfied between parties
Emits: SwapComplete(swapNumber, restrictedTokenSender, restrictedTokenAmount, quoteTokenSender, quoteToken, quoteTokenAmount)
cancelSwap(uint256 swapNumber_)
Cancels a configured swap.
Parameters:
swapNumber_(uint256): The swap number to cancel
Requirements:
- Swap must not be canceled or already completed
- Swap must be properly configured
- For SellConfigured swaps: caller must be the restricted token sender
- For BuyConfigured swaps: caller must be the quote token sender
Emits: SwapCanceled(sender, swapNumber)
Query Functions
swapNumber() → uint256
Returns the current swap number counter.
Returns:
uint256: The current swap number (total swaps configured)
swapStatus(uint256 swapNumber_) → SwapStatus
Returns the status of a specific swap.
Parameters:
swapNumber_(uint256): The swap number to query
Returns:
SwapStatus: The status enum (SellConfigured=1, BuyConfigured=2, Complete=3, Canceled=4)
Requirements:
- Swap record must exist
requiredAllowance(address addr, address token) → uint256
Returns the required allowance for active swaps for a wallet and token.
Parameters:
addr(address): Wallet addresstoken(address): Token address
Returns:
uint256: Required allowance amount for the configurator
requiredAllowanceCounterparty(address addr, address token) → uint256
Returns the required allowance for active swaps as a counterparty.
Parameters:
addr(address): Wallet addresstoken(address): Token address
Returns:
uint256: Required allowance amount as counterparty (informational only)
pendingBuys(address addr) → uint256
Returns pending restricted tokens to buy for an address.
Parameters:
addr(address): Buyer address
Returns:
uint256: Amount of pending restricted tokens to buy
pendingSells(address addr) → uint256
Returns pending restricted tokens to sell for an address.
Parameters:
addr(address): Seller address
Returns:
uint256: Amount of pending restricted tokens to sell
restrictedLockupToken() → address
Returns the RestrictedLockupToken contract address.
Returns:
address: The RestrictedLockupToken contract address
accessControl() → address
Returns the AccessControl contract address.
Returns:
address: The AccessControl contract address
INTERFACE_ID() → bytes4
Returns the interface ID for ERC-165 support.
Returns:
bytes4: The interface identifier
_swapNumber() → uint256
Returns the internal swap number counter (same as swapNumber()).
Returns:
uint256: The current swap number