Skip to content

Solidity contracts for Delegate Market protocol

Notifications You must be signed in to change notification settings

delegatexyz/delegate-market

Repository files navigation

Liquid Delegate

Liquid Delegate is a protocol to tokenize the delegation rights of your spot ERC721s, ERC20s, and ERC1155s. Users deposit a spot asset and receive two tokens in return: the Delegate Token and the Principal Token. The Delegate Token represents the delegation (utility) rights for the chosen duration and the Principal Token represents the rights to claim the underlying escrowed asset at expiration.

Contracts

Describes the upper-level contracts.

  • DelegateToken: Manages the core delegate rights, stores the underlying NFTs and keeps track of expiries.
  • PrincipalToken: Keeps track of the principal owner.
  • CreateOfferer: Seaport contract offerer to allow for direct creation and sale of delegate tokens as part of an order with existing conduit approvals.

Technical Details

Principal-Delegate Token Duality

Unlike V1, Liquid Delegate V2 is a dual token system. Not only does V2 tokenize the delegation rights as transferrable, tradeable ERC721 tokens but also tokenizes the right to withdraw the underlying token once the rights expire. In V1 this right would remain fixed and assigned to the original depositor until the claim expired. Tokenization of the "right to principal" allows for the underlying token to still be traded, transferred and sold while the underlying token is locked in the DelegateToken contract. The delegate rights tokens or just "delegate tokens" for short are tracked in the DelegateToken contract and the principal rights tokens are tracked in the PrincipalToken contract, together they'll be referred to as "rights tokens".

Rights Lifecycle

Diagram: The state and transitions of a pair of rights.

WARNING: The delegate token will be force burned when the principal holder redeems their token after the rights expire. Make sure you only deposit your delegate token into secondary contracts for the duration of the expiry to avoid certain protocol / lending positions that might expect all deposited tokens to be transferrable.

Supported Tokens

WARNING: The protocol makes assumptions about the behavior of deposited tokens, so it's important to check that the token used for deposit is compatible.

At a minimum, when depositing a token with the ERC721 type, the token contract:

  • MUST conform to the EIP721 standard and have normal accounting and transfer behavior and no forced minting / burning.
  • MUST revert if the contract is called with the EIP20 allowance interface.
  • MUST NOT make external calls with the onERC1155Received interface.

At a minimum, when depositing a token with the ERC20 type, the token contract:

  • MUST conform to the EIP20 standard and have normal accounting and transfer behavior and no forced minting / burning.
  • MUST revert if the contract is called with the EIP721 ownerOf interface.
  • MUST NOT make external calls with the onERC1155Received interface.

At a minimum, when depositing a token with the ERC1155 type, the token contract:

  • MUST conform to the EIP1155 standard and have normal accounting and transfer behavior and no forced minting / burning.
  • MUST revert if the contract is called with the EIP721 ownerOf interface.
  • MUST revert if the contract is called with the EIP20 allowance interface.

Seaport-based Rights Creation via CreateOfferer

The CreateOfferer contract is a Seaport "contract offerer" that facilitates the creation of V2 delegation rights directly via Seaport orders. This is done via the CONTRACT order type which allows contracts to dynamically create orders on the fly based on arbitrary data via a standardized interface.

Like any participant in a Seaport order contract offerers also have offers (items they give up) and considerations (items they expect to receive / others to receive) for their orders to validated. The core order generated by the CreateOfferer is very simple:

Offer items (1):

  • A hash receipt that, on transfer by the seaport conduit during a seaport order, forces the creation of the dual delegate tokens.

Consideration items (1):

  • The underlying token that will be used by CreateOfferer to create the corresponding dual delegate tokens by calling DelegateToken.

WARNING: Orders should be carefully constructed to ensure they have the intended effect.

CreateOfferer hash

The deterministic CreateOfferer hash and corresponding DelegateToken id can be obtained by calling the calculate[ERC721/ERC20/ERC1155]OrderHashAndId method on CreateOfferer with three important parameters:

  • targetTokenReceiver is the address that the targetToken, which is the principal or delegate token, should be sent to.
  • conduit is the address of the conduit you specify in your seaport order, which will call transferFrom on CreateOfferer to create the delegate tokens.
  • ERC721Order, ERC20Order, or ERC1155Order struct which contains important information about the targetToken for the targetTokenReceiver, the information about the expiry / underlying token to be used by DelegateToken.

Used correctly, the hash should enable the intent of targetTokenReceiver to receive either the principal or delegate token corresponding to a particular DelegateToken during a seaport order.

CreateOffer context

As part of contract orders seaport allows the inclusion of additional 'context' data in the extraData field. For the CreateOfferer contract the context contains the additional data that cannot be included in the contract offer and consideration data. In order for the contract order to execute correctly, the context must be abi encoded (un packed) with the Context struct in the CreateOffererStructs library.

See the ./test/CreateOfferer.t.sol file for examples on how to use the contract offerer.