Skip to main content

BridgePool

BridgePool#

Contract deployed on L1 that provides methods for "Relayers" to fulfill deposit orders that originated on L2. The Relayers can either post capital to fulfill the deposit (instant relay), or request that the funds are taken out of a passive liquidity provider pool following a challenge period (slow relay). This contract ingests liquidity from passive liquidity providers and returns them claims to withdraw their funds. Liquidity providers are incentivized to post collateral by earning a fee per fulfilled deposit order.

A "Deposit" is an order to send capital from L2 to L1, and a "Relay" is a fulfillment attempt of that order.

Functions#

constructor(string _lpTokenName, string _lpTokenSymbol, address _bridgeAdmin, address _l1Token, uint64 _lpFeeRatePerSecond, bool _isWethPool, address _timer) (public)

Construct the Bridge Pool.

Parameters:#

  • _lpTokenName: Name of the LP token to be deployed by this contract.
  • _lpTokenSymbol: Symbol of the LP token to be deployed by this contract.
  • _bridgeAdmin: Admin contract deployed alongside on L1. Stores global variables and has owner control.
  • _l1Token: Address of the L1 token that this bridgePool holds. This is the token LPs deposit and is bridged.
  • _lpFeeRatePerSecond: Interest rate payment that scales the amount of pending fees per second paid to LPs.
  • _isWethPool: Toggles if this is the WETH pool. If it is then can accept ETH and wrap to WETH for the user.
  • _timer: Timer used to synchronize contract time in testing. Set to 0x000... in production.
addLiquidity(uint256 l1TokenAmount) (public)

Add liquidity to the bridge pool. Pulls l1Token from the caller's wallet. The caller is sent back a commensurate number of LP tokens (minted to their address) at the prevailing exchange rate.

The caller must approve this contract to transfer l1TokenAmount amount of l1Token if depositing ERC20. The caller can deposit ETH which is auto wrapped to WETH. This can only be done if: a) this is the Weth pool and b) the l1TokenAmount matches to the transaction msg.value. Reentrancy guard not added to this function because this indirectly calls sync() which is guarded.

Parameters:#

  • l1TokenAmount: Number of l1Token to add as liquidity.
removeLiquidity(uint256 lpTokenAmount, bool sendEth) (public)

Removes liquidity from the bridge pool. Burns lpTokenAmount LP tokens from the caller's wallet. The caller is sent back a commensurate number of l1Tokens at the prevailing exchange rate.

The caller does not need to approve the spending of LP tokens as this method directly uses the burn logic. Reentrancy guard not added to this function because this indirectly calls sync() which is guarded.

Parameters:#

  • lpTokenAmount: Number of lpTokens to redeem for underlying.
  • sendEth: Enable the liquidity provider to remove liquidity in ETH, if this is the WETH pool.
relayAndSpeedUp(struct BridgePool.DepositData depositData, uint64 realizedLpFeePct) (public)

Called by Relayer to execute a slow + fast relay from L2 to L1, fulfilling a corresponding deposit order.

There can only be one pending relay for a deposit. This method is effectively the relayDeposit and speedUpRelay methods concatenated. This could be refactored to just call each method, but there are some gas savings in combining the transfers and hash computations. Caller must have approved this contract to spend the total bond + amount - fees for l1Token. This function can only be called if relays are enabled for this bridge pool.

Parameters:#

  • depositData: the deposit data struct containing all the user's deposit information.
  • realizedLpFeePct: LP fee calculated off-chain considering the L1 pool liquidity at deposit time, before quoteTimestamp. The OO acts to verify the correctness of this realized fee. Cannot exceed 50%.
disputeRelay(struct BridgePool.DepositData depositData, struct BridgePool.RelayData relayData) (public)

Called by Disputer to dispute an ongoing relay.

The result of this method is to always throw out the relay, providing an opportunity for another relay for the same deposit. Between the disputer and proposer, whoever is incorrect loses their bond. Whoever is correct gets it back + a payout. Caller must have approved this contract to spend the total bond + amount - fees for l1Token.

Parameters:#

  • depositData: the deposit data struct containing all the user's deposit information.
  • relayData: RelayData logged in the disputed relay.
relayDeposit(struct BridgePool.DepositData depositData, uint64 realizedLpFeePct) (public)

Called by Relayer to execute a slow relay from L2 to L1, fulfilling a corresponding deposit order.

There can only be one pending relay for a deposit. Caller must have approved this contract to spend the total bond + amount - fees for l1Token. This function can only be called if relays are enabled for this bridge pool.

Parameters:#

  • depositData: the deposit data struct containing all the user's deposit information.
  • realizedLpFeePct: LP fee calculated off-chain considering the L1 pool liquidity at deposit time, before quoteTimestamp. The OO acts to verify the correctness of this realized fee. Cannot exceed 50%.
speedUpRelay(struct BridgePool.DepositData depositData, struct BridgePool.RelayData relayData) (public)

Instantly relay a deposit amount minus fees to the l1Recipient. Instant relayer earns a reward following the pending relay challenge period.

We assume that the caller has performed an off-chain check that the deposit data they are attempting to relay is valid. If the deposit data is invalid, then the instant relayer has no recourse to receive their funds back after the invalid deposit data is disputed. Moreover, no one will be able to resubmit a relay for the invalid deposit data because they know it will get disputed again. On the other hand, if the deposit data is valid, then even if it is falsely disputed, the instant relayer will eventually get reimbursed because someone else will be incentivized to resubmit the relay to earn slow relayer rewards. Once the valid relay is finalized, the instant relayer will be reimbursed. Therefore, the caller has the same responsibility as the disputer in validating the relay data. Caller must have approved this contract to spend the deposit amount of L1 tokens to relay. There can only be one instant relayer per relay attempt. You cannot speed up a relay that is past liveness.

Parameters:#

  • depositData: Unique set of L2 deposit data that caller is trying to instantly relay.
  • relayData: Parameters of Relay that caller is attempting to speedup. Must hash to the stored relay hash for this deposit or this method will revert.
settleRelay(struct BridgePool.DepositData depositData, struct BridgePool.RelayData relayData) (public)

Reward relayers if a pending relay price request has a price available on the OptimisticOracle. Mark the relay as complete.

We use the relayData and depositData to compute the ancillary data that the relay price request is uniquely associated with on the OptimisticOracle. If the price request passed in does not match the pending relay price request, then this will revert.

Parameters:#

  • depositData: Unique set of L2 deposit data that caller is trying to settle a relay for.
  • relayData: Parameters of Relay that caller is attempting to settle. Must hash to the stored relay hash for this deposit.
sync() (public)

Synchronize any balance changes in this contract with the utilized & liquid reserves. This would be done at the conclusion of an L2 -> L1 token transfer via the canonical token bridge.

exchangeRateCurrent() โ†’ uint256 (public)

Computes the exchange rate between LP tokens and L1Tokens. Used when adding/removing liquidity.

liquidityUtilizationCurrent() โ†’ uint256 (public)

Computes the current liquidity utilization ratio.

Used in computing realizedLpFeePct off-chain.

liquidityUtilizationPostRelay(uint256 relayedAmount) โ†’ uint256 (public)

Computes the liquidity utilization ratio post a relay of known size.

Used in computing realizedLpFeePct off-chain.

Parameters:#

  • relayedAmount: Size of the relayed deposit to factor into the utilization calculation.
getLiquidityUtilization(uint256 relayedAmount) โ†’ uint256 utilizationCurrent, uint256 utilizationPostRelay (public)

Return both the current utilization value and liquidity utilization post the relay.

Used in computing realizedLpFeePct off-chain.

Parameters:#

  • relayedAmount: Size of the relayed deposit to factor into the utilization calculation.
syncUmaEcosystemParams() (public)

Updates the address stored in this contract for the OptimisticOracle and the Store to the latest versions set in the the Finder. Also pull finalFee Store these as local variables to make relay methods gas efficient.

There is no risk of leaving this function public for anyone to call as in all cases we want the addresses in this contract to map to the latest version in the Finder and store the latest final fee.

syncWithBridgeAdminParams() (public)

Updates the values of stored constants for the proposerBondPct, optimisticOracleLiveness and identifier to that set in the bridge Admin. We store these as local variables to make the relay methods more gas efficient.

There is no risk of leaving this function public for anyone to call as in all cases we want these values in this contract to map to the latest version set in the BridgeAdmin.

changeAdmin(address _newAdmin) (public)

Enable the current bridge admin to transfer admin to to a new address.

Caller must be BridgeAdmin contract.

Parameters:#

  • _newAdmin: Admin address of the new admin.
setLpFeeRatePerSecond(uint64 _newLpFeeRatePerSecond) (public)

Enable the bridge admin to change the decay rate at which LP shares accumulate fees. The higher this value, the faster LP shares realize pending fees.

Caller must be BridgeAdmin contract.

Parameters:#

  • _newLpFeeRatePerSecond: The new rate to set.
setRelaysEnabled(bool _relaysEnabled) (public)

Enable the bridge admin to enable/disable relays for this pool. Acts as a pause. Only effects relayDeposit and relayAndSpeedUp methods. ALl other contract logic remains functional after a pause.

Caller must be BridgeAdmin contract.

Parameters:#

  • _relaysEnabled: The new relaysEnabled state.
getAccumulatedFees() โ†’ uint256 (public)

Computes the current amount of unallocated fees that have accumulated from the previous time this the contract was called.

getRelayAncillaryData(struct BridgePool.DepositData depositData, struct BridgePool.RelayData relayData) โ†’ bytes (public)

Returns ancillary data containing all relevant Relay data that voters can format into UTF8 and use to determine if the relay is valid.

Helpful method to test that ancillary data is constructed properly. We should consider removing if we don't anticipate off-chain bots or users to call this method.

Parameters:#

  • depositData: Contains L2 deposit information used by off-chain validators to validate relay.
  • relayData: Contains relay information used by off-chain validators to validate relay.
_liquidityUtilizationPostRelay(uint256 relayedAmount) โ†’ uint256 (internal)
_sync() (internal)
_exchangeRateCurrent() โ†’ uint256 (internal)
_getAccumulatedFees() โ†’ uint256 (internal)
_updateAccumulatedLpFees() (internal)
_allocateLpFees(uint256 allocatedLpFees) (internal)
_unwrapWETHTo(address payable to, uint256 amount) (internal)
receive() (external)
_preEntranceCheck() (internal)
_preEntranceSet() (internal)
_postEntranceReset() (internal)
name() โ†’ string (public)

Returns the name of the token.

symbol() โ†’ string (public)

Returns the symbol of the token, usually a shorter version of the name.

decimals() โ†’ uint8 (public)

Returns the number of decimals used to get its user representation. For example, if decimals equals 2, a balance of 505 tokens should be displayed to a user as 5.05 (505 / 10 ** 2). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for display purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.

totalSupply() โ†’ uint256 (public)

See {IERC20-totalSupply}.

balanceOf(address account) โ†’ uint256 (public)

See {IERC20-balanceOf}.

transfer(address recipient, uint256 amount) โ†’ bool (public)

See {IERC20-transfer}. Requirements:

  • recipient cannot be the zero address.
  • the caller must have a balance of at least amount.
allowance(address owner, address spender) โ†’ uint256 (public)

See {IERC20-allowance}.

approve(address spender, uint256 amount) โ†’ bool (public)

See {IERC20-approve}. Requirements:

  • spender cannot be the zero address.
transferFrom(address sender, address recipient, uint256 amount) โ†’ bool (public)

See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements:

  • sender and recipient cannot be the zero address.
  • sender must have a balance of at least amount.
  • the caller must have allowance for sender's tokens of at least amount.
increaseAllowance(address spender, uint256 addedValue) โ†’ bool (public)

Atomically increases the allowance granted to spender by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements:

  • spender cannot be the zero address.
decreaseAllowance(address spender, uint256 subtractedValue) โ†’ bool (public)

Atomically decreases the allowance granted to spender by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements:

  • spender cannot be the zero address.
  • spender must have allowance for the caller of at least subtractedValue.
_transfer(address sender, address recipient, uint256 amount) (internal)

Moves amount of tokens from sender to recipient. This internal function is equivalent to {transfer}, and can be used to e.g. implement automatic token fees, slashing mechanisms, etc. Emits a {Transfer} event. Requirements:

  • sender cannot be the zero address.
  • recipient cannot be the zero address.
  • sender must have a balance of at least amount.
_mint(address account, uint256 amount) (internal)

Creates amount tokens and assigns them to account, increasing the total supply. Emits a {Transfer} event with from set to the zero address. Requirements:

  • account cannot be the zero address.
_burn(address account, uint256 amount) (internal)

Destroys amount tokens from account, reducing the total supply. Emits a {Transfer} event with to set to the zero address. Requirements:

  • account cannot be the zero address.
  • account must have at least amount tokens.
_approve(address owner, address spender, uint256 amount) (internal)

Sets amount as the allowance of spender over the owner s tokens. This internal function is equivalent to approve, and can be used to e.g. set automatic allowances for certain subsystems, etc. Emits an {Approval} event. Requirements:

  • owner cannot be the zero address.
  • spender cannot be the zero address.
_beforeTokenTransfer(address from, address to, uint256 amount) (internal)

Hook that is called before any transfer of tokens. This includes minting and burning. Calling conditions:

  • when from and to are both non-zero, amount of from's tokens will be transferred to to.
  • when from is zero, amount tokens will be minted for to.
  • when to is zero, amount of from's tokens will be burned.
  • from and to are never both zero. To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
_afterTokenTransfer(address from, address to, uint256 amount) (internal)

Hook that is called after any transfer of tokens. This includes minting and burning. Calling conditions:

  • when from and to are both non-zero, amount of from's tokens has been transferred to to.
  • when from is zero, amount tokens have been minted for to.
  • when to is zero, amount of from's tokens have been burned.
  • from and to are never both zero. To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
_msgSender() โ†’ address (internal)
_msgData() โ†’ bytes (internal)
l1Token() โ†’ contract IERC20 (external)
setCurrentTime(uint256 time) (external)

Sets the current time.

Will revert if not running in test mode.

Parameters:#

  • time: timestamp to set current Testable time to.
getCurrentTime() โ†’ uint256 (public)

Gets the current time. Will return the last time set in setCurrentTime if running in test mode. Otherwise, it will return the block timestamp.

multicall(bytes[] data) โ†’ bytes[] results (external)

Events#

LiquidityAdded(uint256 amount, uint256 lpTokensMinted, address liquidityProvider)
LiquidityRemoved(uint256 amount, uint256 lpTokensBurnt, address liquidityProvider)
DepositRelayed(bytes32 depositHash, struct BridgePool.DepositData depositData, struct BridgePool.RelayData relay, bytes32 relayAncillaryDataHash)
RelaySpedUp(bytes32 depositHash, address instantRelayer, struct BridgePool.RelayData relay)
RelayDisputed(bytes32 depositHash, bytes32 relayHash, address disputer)
RelayCanceled(bytes32 depositHash, bytes32 relayHash, address disputer)
RelaySettled(bytes32 depositHash, address caller, struct BridgePool.RelayData relay)
BridgePoolAdminTransferred(address oldAdmin, address newAdmin)
RelaysEnabledSet(bool newRelaysEnabled)
LpFeeRateSet(uint64 newLpFeeRatePerSecond)
Transfer(address from, address to, uint256 value)

Emitted when value tokens are moved from one account (from) to another (to). Note that value may be zero.

Approval(address owner, address spender, uint256 value)

Emitted when the allowance of a spender for an owner is set by a call to {approve}. value is the new allowance.

Modifiers#

onlyBridgeAdmin()
onlyIfRelaysEnabld()
nonReentrant()

Prevents a contract from calling itself, directly or indirectly. Calling a nonReentrant function from another nonReentrant function is not supported. It is possible to prevent this from happening by making the nonReentrant function external, and making it call a private function that does the actual state modification.

nonReentrantView()

Designed to prevent a view-only method from being re-entered during a call to a nonReentrant() state-changing method.

onlyIfTest()

Reverts if not running in test mode.