# **Element Bridge Implementation** The element bridge serves to manage the aggregated deposits of client funds into element pools and automatically redeem those pools once the deposit term has expired. # High level concepts **Yearn Vault** Most (possibly all) of the deposits with Element are backed by the Yearn finance protocol which provides yield for staked assets. **Underlying asset** An ERC20 token that the user owns and wishes to deposit to generate a return. e.g. DAI, USDC etc **Wrapped position** An ERC20 that serves as a proxy to the underlying asset held within a Yearn vault. **Element protocol** The Element protocol serves to provide a fixed rate return mechanism in front of Yearn producing a set of asset/expiry combinations. It does this by splitting deposits into 2 components, the Principle Token (PT) and the Yield Token (YT). The PT is designed to be a 1:1 swap for the deposited asset and the YT represents the variable yield. These tokens are themselves ERC20 tokens and can be traded on the secondary market. The PT tokens are traded on the Balancer AMM platform and typically trade at a discount to the underlying asset, representing the fact that the PT is effectively 'locked' up until expiry. **Element Tranche** A pool of deposits of a single asset (e.g. DAI stablecoin) that is 'locked' until some time in the future, the expiry. **Convergent Pool** The automated market maker protocol operated by Balancer used to swap the underlying asset for Element principle tokens. The following diagram, taken from the Element site goes some way to illustrate some of these concepts. ![](https://hackmd.io/_uploads/ByZPj1Mfq.png) # High level bridge operation **Converting interactions** If an Aztec user wishes to earn a fixed rate return by depositing an ERC20 they can perform a Defi deposit for a given bridge id. The bridge id specifies the asset they are depositing and the expiry they have selected. The rollup provider groups this transaction along with any number of other transactions for the same asset and expiry and sends them to the Element bridge. This single aggregation is termed an Interaction. Every time the bridge receives an interaction it does the following: 1. Take the input asset address and expiry and lookup the appropriate Element Tranche and corresponding PT. 2. Exchange the total provided underlying asset for the Tranche PT via the Balancer AMM platform. 3. Update the total sum of PT for that Tranche across all interactions with the amount received from Balancer. 4. Check to see if there are any interactions that can be 'Finalised'. Finalising an interaction means giving the PT tokens back to element in exchange for the proportionate quantity of the underlying asset. Effectively making the withdrawal. **Finalising interactions** Once an Element Tranche has 'matured', the bridge begins the process of giving users back the funds that are owed to them. As stated above, the bridge tracks to total amount of Tranche PT that it has in it's posession. So, the first time we withdraw the underlying, we withdraw all of the underlying owed to all interactions for that Tranche. After that, it simply apportions the correct amount of the underlying asset to the interactions in that tranche. This allows us to return the assets more quickly as we operate with an upper limit on the amount of gas. **Configuring the pools** For an asset/expiry combination to be available, it first has to be configured on the bridge. This is done by calling a method on the contract and providing 3 values. 1. The wrapped position address 2. The expiry value (unix timestamp) 3. The Balancer pool address from which we can obtain PT tokens The actual Tranche address is derived from the wrapped position address and the expiry using the Create2 deterministic address system. # **Contract Implementation** # Entities and Mappings To manage the above interactions, tranches etc. The contract defines the following entities and mappings. ![](https://hackmd.io/_uploads/rJV80-MM9.png) **Pool** The pool entity is added to the system when an external party configures and new convergent pool. It is stored within a mapping keyed on the hash of the concatenation of asset and expiry. It's primary purpose is to identity which balancer pool to use to retrieve Principal Tokens and which Element Tranche they correspond to. It is only used when new interactions are sent to the bridge. Once an interaction has acquired it's balance of PT, the pool is no longer required for that interaction. **TrancheAccount** This entity is used to track the total quantity of a given Principal Token held by the contract, how much underlying asset is received upon redemption and how much is still to be apportioned to finalised interactions. These are stored within a mapping keyed on the Tranche Address. **Interaction** The interaction entity holds all state required to track and process a single bridge interaction. They are stored in a mapping keyed on Interaction nonce. They are added to the system at the point of a new interaction being sent to the bridge. # The Expiry Heap As mentioned above, once a new interaction has been successfully created, the bridge will attempt to finalise any matured deposits. To do this efficiently it maintains 2 data structures. The first is a mapping of expiry to interaction nonces. Upon receipt of a new interaction, it's nonce is added against the expiry value in this mapping. ![](https://hackmd.io/_uploads/BJ9_4fzM5.png) The second is simply an array of expiries, structured as a minimum heap. The following describes the operation of these data structures. 1. Upon creation of a new interaction, the nonce is added against it's expiry value in the expiry -> nonce mapping. This is an O(1) operation. 2. If it's the first nonce against that expiry, the expiry is added to the expiry heap, being a minimum heap, this is a O(logN) operation, where N is the current number of expiries. 3. Once an interaction is finalised, it is removed from the array of nonces against it's expiry. This is an O(1) operation. Once all interations for an expiry have been finalised, the expiry is removed from the heap. If the expiry is the earliest (i.e. it is the minimum value in the heap) then this operation is O(logN). 4. After an interaction has been created, the bridge will finalise 1 or more interactions that have matured. To do this, it checks the minimum value in the heap (the earliest available expiry) and if this is older than the current time, it looks up the array of nonces in the expiry -> nonce mapping and selects the nonce at the end of the array. These are both O(1) operations