@across-protocol/contracts 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +661 -0
  3. package/README.md +53 -0
  4. package/artifacts/@eth-optimism/contracts/L2/messaging/IL2ERC20Bridge.sol/IL2ERC20Bridge.dbg.json +4 -0
  5. package/artifacts/@eth-optimism/contracts/L2/messaging/IL2ERC20Bridge.sol/IL2ERC20Bridge.json +252 -0
  6. package/artifacts/@eth-optimism/contracts/libraries/bridge/CrossDomainEnabled.sol/CrossDomainEnabled.dbg.json +4 -0
  7. package/artifacts/@eth-optimism/contracts/libraries/bridge/CrossDomainEnabled.sol/CrossDomainEnabled.json +35 -0
  8. package/artifacts/@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol/ICrossDomainMessenger.dbg.json +4 -0
  9. package/artifacts/@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol/ICrossDomainMessenger.json +110 -0
  10. package/artifacts/@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol/Lib_PredeployAddresses.dbg.json +4 -0
  11. package/artifacts/@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol/Lib_PredeployAddresses.json +10 -0
  12. package/artifacts/@openzeppelin/contracts/access/AccessControl.sol/AccessControl.dbg.json +4 -0
  13. package/artifacts/@openzeppelin/contracts/access/AccessControl.sol/AccessControl.json +215 -0
  14. package/artifacts/@openzeppelin/contracts/access/AccessControl.sol/IAccessControl.dbg.json +4 -0
  15. package/artifacts/@openzeppelin/contracts/access/AccessControl.sol/IAccessControl.json +108 -0
  16. package/artifacts/@openzeppelin/contracts/access/Ownable.sol/Ownable.dbg.json +4 -0
  17. package/artifacts/@openzeppelin/contracts/access/Ownable.sol/Ownable.json +63 -0
  18. package/artifacts/@openzeppelin/contracts/security/Pausable.sol/Pausable.dbg.json +4 -0
  19. package/artifacts/@openzeppelin/contracts/security/Pausable.sol/Pausable.json +50 -0
  20. package/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.dbg.json +4 -0
  21. package/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.json +297 -0
  22. package/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.dbg.json +4 -0
  23. package/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.json +194 -0
  24. package/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.dbg.json +4 -0
  25. package/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.json +233 -0
  26. package/artifacts/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol/SafeERC20.dbg.json +4 -0
  27. package/artifacts/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol/SafeERC20.json +10 -0
  28. package/artifacts/@openzeppelin/contracts/utils/Address.sol/Address.dbg.json +4 -0
  29. package/artifacts/@openzeppelin/contracts/utils/Address.sol/Address.json +10 -0
  30. package/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json +4 -0
  31. package/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.json +10 -0
  32. package/artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.dbg.json +4 -0
  33. package/artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.json +10 -0
  34. package/artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.dbg.json +4 -0
  35. package/artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.json +30 -0
  36. package/artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.dbg.json +4 -0
  37. package/artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.json +30 -0
  38. package/artifacts/@openzeppelin/contracts/utils/math/SafeMath.sol/SafeMath.dbg.json +4 -0
  39. package/artifacts/@openzeppelin/contracts/utils/math/SafeMath.sol/SafeMath.json +10 -0
  40. package/artifacts/@openzeppelin/contracts/utils/math/SignedSafeMath.sol/SignedSafeMath.dbg.json +4 -0
  41. package/artifacts/@openzeppelin/contracts/utils/math/SignedSafeMath.sol/SignedSafeMath.json +10 -0
  42. package/artifacts/@uma/core/contracts/common/implementation/Lockable.sol/Lockable.dbg.json +4 -0
  43. package/artifacts/@uma/core/contracts/common/implementation/Lockable.sol/Lockable.json +16 -0
  44. package/artifacts/@uma/core/contracts/cross-chain-oracle/chain-adapters/Arbitrum_ParentMessenger.sol/Arbitrum_ParentMessenger.dbg.json +4 -0
  45. package/artifacts/@uma/core/contracts/cross-chain-oracle/chain-adapters/Arbitrum_ParentMessenger.sol/Arbitrum_ParentMessenger.json +611 -0
  46. package/artifacts/@uma/core/contracts/cross-chain-oracle/chain-adapters/ParentMessengerBase.sol/ParentMessengerBase.dbg.json +4 -0
  47. package/artifacts/@uma/core/contracts/cross-chain-oracle/chain-adapters/ParentMessengerBase.sol/ParentMessengerBase.json +297 -0
  48. package/artifacts/@uma/core/contracts/cross-chain-oracle/interfaces/ParentMessengerConsumerInterface.sol/ParentMessengerConsumerInterface.dbg.json +4 -0
  49. package/artifacts/@uma/core/contracts/cross-chain-oracle/interfaces/ParentMessengerConsumerInterface.sol/ParentMessengerConsumerInterface.json +29 -0
  50. package/artifacts/@uma/core/contracts/cross-chain-oracle/interfaces/ParentMessengerInterface.sol/ParentMessengerInterface.dbg.json +4 -0
  51. package/artifacts/@uma/core/contracts/cross-chain-oracle/interfaces/ParentMessengerInterface.sol/ParentMessengerInterface.json +37 -0
  52. package/artifacts/@uma/core/contracts/external/avm/interfaces/iArbitrum_Inbox.sol/IBridge.dbg.json +4 -0
  53. package/artifacts/@uma/core/contracts/external/avm/interfaces/iArbitrum_Inbox.sol/IBridge.json +24 -0
  54. package/artifacts/@uma/core/contracts/external/avm/interfaces/iArbitrum_Inbox.sol/iArbitrum_Inbox.dbg.json +4 -0
  55. package/artifacts/@uma/core/contracts/external/avm/interfaces/iArbitrum_Inbox.sol/iArbitrum_Inbox.json +78 -0
  56. package/artifacts/@uma/core/contracts/external/avm/interfaces/iArbitrum_Outbox.sol/iArbitrum_Outbox.dbg.json +4 -0
  57. package/artifacts/@uma/core/contracts/external/avm/interfaces/iArbitrum_Outbox.sol/iArbitrum_Outbox.json +24 -0
  58. package/artifacts/@uma/core/contracts/insured-bridge/avm/Arbitrum_CrossDomainEnabled.sol/Arbitrum_CrossDomainEnabled.dbg.json +4 -0
  59. package/artifacts/@uma/core/contracts/insured-bridge/avm/Arbitrum_CrossDomainEnabled.sol/Arbitrum_CrossDomainEnabled.json +24 -0
  60. package/artifacts/build-info/1cd64db7a8ac0a153df93d26826ad4e9.json +1653 -0
  61. package/artifacts/build-info/1f738b56edd7602183f2f8d2f23f6e90.json +1592 -0
  62. package/artifacts/build-info/343b9221be36acd9ddaca3f3b83d2e75.json +3943 -0
  63. package/artifacts/build-info/622e561692c193f4cd0ff989b5a231e2.json +5661 -0
  64. package/artifacts/build-info/8e408b49e0ff2873bc28d45221a7ff71.json +277715 -0
  65. package/artifacts/build-info/9d1a3182633612bd337d811d567d5d60.json +2072 -0
  66. package/artifacts/build-info/a8cd9c443d245fe513d6650634b60f93.json +23776 -0
  67. package/artifacts/build-info/d302d9d63fbafb5c8d635cc62cb1cc7c.json +167529 -0
  68. package/artifacts/contracts/common/implementation/AncillaryData.sol/AncillaryData.dbg.json +4 -0
  69. package/artifacts/contracts/common/implementation/AncillaryData.sol/AncillaryData.json +10 -0
  70. package/artifacts/contracts/common/implementation/FixedPoint.sol/FixedPoint.dbg.json +4 -0
  71. package/artifacts/contracts/common/implementation/FixedPoint.sol/FixedPoint.json +10 -0
  72. package/artifacts/contracts/common/implementation/Lockable.sol/Lockable.dbg.json +4 -0
  73. package/artifacts/contracts/common/implementation/Lockable.sol/Lockable.json +16 -0
  74. package/artifacts/contracts/common/implementation/MultiCaller.sol/MultiCaller.dbg.json +4 -0
  75. package/artifacts/contracts/common/implementation/MultiCaller.sol/MultiCaller.json +30 -0
  76. package/artifacts/contracts/common/implementation/Testable.sol/Testable.dbg.json +4 -0
  77. package/artifacts/contracts/common/implementation/Testable.sol/Testable.json +50 -0
  78. package/artifacts/contracts/common/implementation/Timer.sol/Timer.dbg.json +4 -0
  79. package/artifacts/contracts/common/implementation/Timer.sol/Timer.json +42 -0
  80. package/artifacts/contracts/common/interfaces/AddressWhitelistInterface.sol/AddressWhitelistInterface.dbg.json +4 -0
  81. package/artifacts/contracts/common/interfaces/AddressWhitelistInterface.sol/AddressWhitelistInterface.json +69 -0
  82. package/artifacts/contracts/external/avm/AVM_CrossDomainEnabled.sol/AVM_CrossDomainEnabled.dbg.json +4 -0
  83. package/artifacts/contracts/external/avm/AVM_CrossDomainEnabled.sol/AVM_CrossDomainEnabled.json +42 -0
  84. package/artifacts/contracts/external/avm/interfaces/ArbSys.sol/ArbSys.dbg.json +4 -0
  85. package/artifacts/contracts/external/avm/interfaces/ArbSys.sol/ArbSys.json +235 -0
  86. package/artifacts/contracts/external/avm/interfaces/iArbitrum_Inbox.sol/IBridge.dbg.json +4 -0
  87. package/artifacts/contracts/external/avm/interfaces/iArbitrum_Inbox.sol/IBridge.json +24 -0
  88. package/artifacts/contracts/external/avm/interfaces/iArbitrum_Inbox.sol/iArbitrum_Inbox.dbg.json +4 -0
  89. package/artifacts/contracts/external/avm/interfaces/iArbitrum_Inbox.sol/iArbitrum_Inbox.json +78 -0
  90. package/artifacts/contracts/external/avm/interfaces/iArbitrum_Outbox.sol/iArbitrum_Outbox.dbg.json +4 -0
  91. package/artifacts/contracts/external/avm/interfaces/iArbitrum_Outbox.sol/iArbitrum_Outbox.json +24 -0
  92. package/artifacts/contracts/external/chainbridge/Bridge.sol/Bridge.dbg.json +4 -0
  93. package/artifacts/contracts/external/chainbridge/Bridge.sol/Bridge.json +1019 -0
  94. package/artifacts/contracts/external/chainbridge/handlers/GenericHandler.sol/GenericHandler.dbg.json +4 -0
  95. package/artifacts/contracts/external/chainbridge/handlers/GenericHandler.sol/GenericHandler.json +314 -0
  96. package/artifacts/contracts/external/chainbridge/interfaces/IBridge.sol/IBridge.dbg.json +4 -0
  97. package/artifacts/contracts/external/chainbridge/interfaces/IBridge.sol/IBridge.json +47 -0
  98. package/artifacts/contracts/external/chainbridge/interfaces/IDepositExecute.sol/IDepositExecute.dbg.json +4 -0
  99. package/artifacts/contracts/external/chainbridge/interfaces/IDepositExecute.sol/IDepositExecute.json +62 -0
  100. package/artifacts/contracts/external/chainbridge/interfaces/IERCHandler.sol/IERCHandler.dbg.json +4 -0
  101. package/artifacts/contracts/external/chainbridge/interfaces/IERCHandler.sol/IERCHandler.json +65 -0
  102. package/artifacts/contracts/external/chainbridge/interfaces/IGenericHandler.sol/IGenericHandler.dbg.json +4 -0
  103. package/artifacts/contracts/external/chainbridge/interfaces/IGenericHandler.sol/IGenericHandler.json +39 -0
  104. package/artifacts/contracts/external/ovm/OVM_CrossDomainEnabled.sol/OVM_CrossDomainEnabled.dbg.json +4 -0
  105. package/artifacts/contracts/external/ovm/OVM_CrossDomainEnabled.sol/OVM_CrossDomainEnabled.json +35 -0
  106. package/artifacts/contracts/external/ovm/OVM_CrossDomainEnabled.sol/iOVM_CrossDomainMessenger.dbg.json +4 -0
  107. package/artifacts/contracts/external/ovm/OVM_CrossDomainEnabled.sol/iOVM_CrossDomainMessenger.json +86 -0
  108. package/artifacts/contracts/external/polygon/lib/Merkle.sol/Merkle.dbg.json +4 -0
  109. package/artifacts/contracts/external/polygon/lib/Merkle.sol/Merkle.json +10 -0
  110. package/artifacts/contracts/external/polygon/lib/MerklePatriciaProof.sol/MerklePatriciaProof.dbg.json +4 -0
  111. package/artifacts/contracts/external/polygon/lib/MerklePatriciaProof.sol/MerklePatriciaProof.json +10 -0
  112. package/artifacts/contracts/external/polygon/lib/RLPReader.sol/RLPReader.dbg.json +4 -0
  113. package/artifacts/contracts/external/polygon/lib/RLPReader.sol/RLPReader.json +10 -0
  114. package/artifacts/contracts/external/polygon/test/FxChildMock.sol/FxChildMock.dbg.json +4 -0
  115. package/artifacts/contracts/external/polygon/test/FxChildMock.sol/FxChildMock.json +104 -0
  116. package/artifacts/contracts/external/polygon/test/FxChildMock.sol/IFxMessageProcessor.dbg.json +4 -0
  117. package/artifacts/contracts/external/polygon/test/FxChildMock.sol/IFxMessageProcessor.json +34 -0
  118. package/artifacts/contracts/external/polygon/test/FxChildMock.sol/IStateReceiver.dbg.json +4 -0
  119. package/artifacts/contracts/external/polygon/test/FxChildMock.sol/IStateReceiver.json +29 -0
  120. package/artifacts/contracts/external/polygon/test/FxRootMock.sol/FxRootMock.dbg.json +4 -0
  121. package/artifacts/contracts/external/polygon/test/FxRootMock.sol/FxRootMock.json +79 -0
  122. package/artifacts/contracts/external/polygon/test/FxRootMock.sol/IFxStateSender.dbg.json +4 -0
  123. package/artifacts/contracts/external/polygon/test/FxRootMock.sol/IFxStateSender.json +29 -0
  124. package/artifacts/contracts/external/polygon/test/FxRootMock.sol/IStateSender.dbg.json +4 -0
  125. package/artifacts/contracts/external/polygon/test/FxRootMock.sol/IStateSender.json +29 -0
  126. package/artifacts/contracts/external/polygon/test/StateSyncMock.sol/StateSyncMock.dbg.json +4 -0
  127. package/artifacts/contracts/external/polygon/test/StateSyncMock.sol/StateSyncMock.json +54 -0
  128. package/artifacts/contracts/external/polygon/tunnel/FxBaseChildTunnel.sol/FxBaseChildTunnel.dbg.json +4 -0
  129. package/artifacts/contracts/external/polygon/tunnel/FxBaseChildTunnel.sol/FxBaseChildTunnel.json +86 -0
  130. package/artifacts/contracts/external/polygon/tunnel/FxBaseChildTunnel.sol/IFxMessageProcessor.dbg.json +4 -0
  131. package/artifacts/contracts/external/polygon/tunnel/FxBaseChildTunnel.sol/IFxMessageProcessor.json +34 -0
  132. package/artifacts/contracts/external/polygon/tunnel/FxBaseRootTunnel.sol/FxBaseRootTunnel.dbg.json +4 -0
  133. package/artifacts/contracts/external/polygon/tunnel/FxBaseRootTunnel.sol/FxBaseRootTunnel.json +108 -0
  134. package/artifacts/contracts/external/polygon/tunnel/FxBaseRootTunnel.sol/ICheckpointManager.dbg.json +4 -0
  135. package/artifacts/contracts/external/polygon/tunnel/FxBaseRootTunnel.sol/ICheckpointManager.json +50 -0
  136. package/artifacts/contracts/external/polygon/tunnel/FxBaseRootTunnel.sol/IFxStateSender.dbg.json +4 -0
  137. package/artifacts/contracts/external/polygon/tunnel/FxBaseRootTunnel.sol/IFxStateSender.json +29 -0
  138. package/artifacts/contracts/insured-bridge/BridgeAdmin.sol/BridgeAdmin.dbg.json +4 -0
  139. package/artifacts/contracts/insured-bridge/BridgeAdmin.sol/BridgeAdmin.json +662 -0
  140. package/artifacts/contracts/insured-bridge/BridgeDepositBox.sol/BridgeDepositBox.dbg.json +4 -0
  141. package/artifacts/contracts/insured-bridge/BridgeDepositBox.sol/BridgeDepositBox.json +391 -0
  142. package/artifacts/contracts/insured-bridge/BridgeDepositBox.sol/TokenLike.dbg.json +4 -0
  143. package/artifacts/contracts/insured-bridge/BridgeDepositBox.sol/TokenLike.json +30 -0
  144. package/artifacts/contracts/insured-bridge/BridgeDepositBox.sol/WETH9Like.dbg.json +4 -0
  145. package/artifacts/contracts/insured-bridge/BridgeDepositBox.sol/WETH9Like.json +31 -0
  146. package/artifacts/contracts/insured-bridge/BridgePool.sol/BridgePool.dbg.json +4 -0
  147. package/artifacts/contracts/insured-bridge/BridgePool.sol/BridgePool.json +1709 -0
  148. package/artifacts/contracts/insured-bridge/BridgePool.sol/BridgePoolProd.dbg.json +4 -0
  149. package/artifacts/contracts/insured-bridge/BridgePool.sol/BridgePoolProd.json +1709 -0
  150. package/artifacts/contracts/insured-bridge/BridgePool.sol/WETH9Like.dbg.json +4 -0
  151. package/artifacts/contracts/insured-bridge/BridgePool.sol/WETH9Like.json +31 -0
  152. package/artifacts/contracts/insured-bridge/avm/AVM_BridgeDepositBox.sol/AVM_BridgeDepositBox.dbg.json +4 -0
  153. package/artifacts/contracts/insured-bridge/avm/AVM_BridgeDepositBox.sol/AVM_BridgeDepositBox.json +564 -0
  154. package/artifacts/contracts/insured-bridge/avm/AVM_BridgeDepositBox.sol/StandardBridgeLike.dbg.json +4 -0
  155. package/artifacts/contracts/insured-bridge/avm/AVM_BridgeDepositBox.sol/StandardBridgeLike.json +45 -0
  156. package/artifacts/contracts/insured-bridge/avm/Arbitrum_CrossDomainEnabled.sol/Arbitrum_CrossDomainEnabled.dbg.json +4 -0
  157. package/artifacts/contracts/insured-bridge/avm/Arbitrum_CrossDomainEnabled.sol/Arbitrum_CrossDomainEnabled.json +24 -0
  158. package/artifacts/contracts/insured-bridge/avm/Arbitrum_Messenger.sol/Arbitrum_Messenger.dbg.json +4 -0
  159. package/artifacts/contracts/insured-bridge/avm/Arbitrum_Messenger.sol/Arbitrum_Messenger.json +191 -0
  160. package/artifacts/contracts/insured-bridge/interfaces/BridgeAdminInterface.sol/BridgeAdminInterface.dbg.json +4 -0
  161. package/artifacts/contracts/insured-bridge/interfaces/BridgeAdminInterface.sol/BridgeAdminInterface.json +319 -0
  162. package/artifacts/contracts/insured-bridge/interfaces/BridgePoolInterface.sol/BridgePoolInterface.dbg.json +4 -0
  163. package/artifacts/contracts/insured-bridge/interfaces/BridgePoolInterface.sol/BridgePoolInterface.json +63 -0
  164. package/artifacts/contracts/insured-bridge/interfaces/MessengerInterface.sol/MessengerInterface.dbg.json +4 -0
  165. package/artifacts/contracts/insured-bridge/interfaces/MessengerInterface.sol/MessengerInterface.json +54 -0
  166. package/artifacts/contracts/insured-bridge/ovm/OVM_BridgeDepositBox.sol/OVM_BridgeDepositBox.dbg.json +4 -0
  167. package/artifacts/contracts/insured-bridge/ovm/OVM_BridgeDepositBox.sol/OVM_BridgeDepositBox.json +528 -0
  168. package/artifacts/contracts/insured-bridge/ovm/OVM_CrossDomainEnabled.sol/OVM_CrossDomainEnabled.dbg.json +4 -0
  169. package/artifacts/contracts/insured-bridge/ovm/OVM_CrossDomainEnabled.sol/OVM_CrossDomainEnabled.json +35 -0
  170. package/artifacts/contracts/insured-bridge/ovm/OVM_OETH_BridgeDepositBox.sol/OVM_OETH_BridgeDepositBox.dbg.json +4 -0
  171. package/artifacts/contracts/insured-bridge/ovm/OVM_OETH_BridgeDepositBox.sol/OVM_OETH_BridgeDepositBox.json +572 -0
  172. package/artifacts/contracts/insured-bridge/ovm/Optimism_Messenger.sol/Optimism_Messenger.dbg.json +4 -0
  173. package/artifacts/contracts/insured-bridge/ovm/Optimism_Messenger.sol/Optimism_Messenger.json +130 -0
  174. package/artifacts/contracts/insured-bridge/ovm/Optimism_Wrapper.sol/Optimism_Wrapper.dbg.json +4 -0
  175. package/artifacts/contracts/insured-bridge/ovm/Optimism_Wrapper.sol/Optimism_Wrapper.json +142 -0
  176. package/artifacts/contracts/insured-bridge/ovm/Optimism_Wrapper.sol/WETH9Like.dbg.json +4 -0
  177. package/artifacts/contracts/insured-bridge/ovm/Optimism_Wrapper.sol/WETH9Like.json +55 -0
  178. package/artifacts/contracts/insured-bridge/ovm/iOVM_CrossDomainMessenger.sol/iOVM_CrossDomainMessenger.dbg.json +4 -0
  179. package/artifacts/contracts/insured-bridge/ovm/iOVM_CrossDomainMessenger.sol/iOVM_CrossDomainMessenger.json +86 -0
  180. package/artifacts/contracts/insured-bridge/test/Arbitrum_InboxMock.sol/Arbitrum_BridgeMock.dbg.json +4 -0
  181. package/artifacts/contracts/insured-bridge/test/Arbitrum_InboxMock.sol/Arbitrum_BridgeMock.json +68 -0
  182. package/artifacts/contracts/insured-bridge/test/Arbitrum_InboxMock.sol/Arbitrum_InboxMock.dbg.json +4 -0
  183. package/artifacts/contracts/insured-bridge/test/Arbitrum_InboxMock.sol/Arbitrum_InboxMock.json +78 -0
  184. package/artifacts/contracts/insured-bridge/test/Arbitrum_InboxMock.sol/Arbitrum_OutboxMock.dbg.json +4 -0
  185. package/artifacts/contracts/insured-bridge/test/Arbitrum_InboxMock.sol/Arbitrum_OutboxMock.json +24 -0
  186. package/artifacts/contracts/insured-bridge/test/BridgeDepositBoxMock.sol/BridgeDepositBoxMock.dbg.json +4 -0
  187. package/artifacts/contracts/insured-bridge/test/BridgeDepositBoxMock.sol/BridgeDepositBoxMock.json +510 -0
  188. package/artifacts/contracts/insured-bridge/test/MessengerMock.sol/MessengerMock.dbg.json +4 -0
  189. package/artifacts/contracts/insured-bridge/test/MessengerMock.sol/MessengerMock.json +85 -0
  190. package/artifacts/contracts/insured-bridge/test/OVM_L1CrossDomainMessengerMock.sol/OVM_L1CrossDomainMessengerMock.dbg.json +4 -0
  191. package/artifacts/contracts/insured-bridge/test/OVM_L1CrossDomainMessengerMock.sol/OVM_L1CrossDomainMessengerMock.json +110 -0
  192. package/artifacts/contracts/oracle/implementation/Constants.sol/OptimisticOracleConstraints.dbg.json +4 -0
  193. package/artifacts/contracts/oracle/implementation/Constants.sol/OptimisticOracleConstraints.json +24 -0
  194. package/artifacts/contracts/oracle/implementation/Constants.sol/OracleInterfaces.dbg.json +4 -0
  195. package/artifacts/contracts/oracle/implementation/Constants.sol/OracleInterfaces.json +141 -0
  196. package/artifacts/contracts/oracle/interfaces/FinderInterface.sol/FinderInterface.dbg.json +4 -0
  197. package/artifacts/contracts/oracle/interfaces/FinderInterface.sol/FinderInterface.json +48 -0
  198. package/artifacts/contracts/oracle/interfaces/IdentifierWhitelistInterface.sol/IdentifierWhitelistInterface.dbg.json +4 -0
  199. package/artifacts/contracts/oracle/interfaces/IdentifierWhitelistInterface.sol/IdentifierWhitelistInterface.json +56 -0
  200. package/artifacts/contracts/oracle/interfaces/OptimisticOracleInterface.sol/OptimisticOracleInterface.dbg.json +4 -0
  201. package/artifacts/contracts/oracle/interfaces/OptimisticOracleInterface.sol/OptimisticOracleInterface.json +555 -0
  202. package/artifacts/contracts/oracle/interfaces/SkinnyOptimisticOracleInterface.sol/SkinnyOptimisticOracleInterface.dbg.json +4 -0
  203. package/artifacts/contracts/oracle/interfaces/SkinnyOptimisticOracleInterface.sol/SkinnyOptimisticOracleInterface.json +853 -0
  204. package/artifacts/contracts/oracle/interfaces/StoreInterface.sol/StoreInterface.dbg.json +4 -0
  205. package/artifacts/contracts/oracle/interfaces/StoreInterface.sol/StoreInterface.json +124 -0
  206. package/contracts/common/implementation/AncillaryData.sol +144 -0
  207. package/contracts/common/implementation/FixedPoint.sol +763 -0
  208. package/contracts/common/implementation/Lockable.sol +61 -0
  209. package/contracts/common/implementation/MultiCaller.sol +27 -0
  210. package/contracts/common/implementation/Testable.sol +52 -0
  211. package/contracts/common/implementation/Timer.sol +30 -0
  212. package/contracts/common/interfaces/AddressWhitelistInterface.sol +12 -0
  213. package/contracts/external/avm/AVM_CrossDomainEnabled.sol +43 -0
  214. package/contracts/external/avm/interfaces/ArbSys.sol +79 -0
  215. package/contracts/external/avm/interfaces/iArbitrum_Inbox.sol +28 -0
  216. package/contracts/external/avm/interfaces/iArbitrum_Outbox.sol +26 -0
  217. package/contracts/external/chainbridge/Bridge.sol +454 -0
  218. package/contracts/external/chainbridge/handlers/GenericHandler.sol +237 -0
  219. package/contracts/external/chainbridge/interfaces/IBridge.sol +20 -0
  220. package/contracts/external/chainbridge/interfaces/IDepositExecute.sol +29 -0
  221. package/contracts/external/chainbridge/interfaces/IERCHandler.sol +33 -0
  222. package/contracts/external/chainbridge/interfaces/IGenericHandler.sol +23 -0
  223. package/contracts/external/ovm/OVM_CrossDomainEnabled.sol +114 -0
  224. package/contracts/external/polygon/lib/Merkle.sol +36 -0
  225. package/contracts/external/polygon/lib/MerklePatriciaProof.sol +139 -0
  226. package/contracts/external/polygon/lib/RLPReader.sol +251 -0
  227. package/contracts/external/polygon/test/FxChildMock.sol +42 -0
  228. package/contracts/external/polygon/test/FxRootMock.sol +32 -0
  229. package/contracts/external/polygon/test/StateSyncMock.sol +26 -0
  230. package/contracts/external/polygon/tunnel/FxBaseChildTunnel.sol +80 -0
  231. package/contracts/external/polygon/tunnel/FxBaseRootTunnel.sol +185 -0
  232. package/contracts/insured-bridge/BridgeAdmin.sol +394 -0
  233. package/contracts/insured-bridge/BridgeDepositBox.sol +245 -0
  234. package/contracts/insured-bridge/BridgePool.sol +980 -0
  235. package/contracts/insured-bridge/avm/AVM_BridgeDepositBox.sol +144 -0
  236. package/contracts/insured-bridge/avm/Arbitrum_CrossDomainEnabled.sol +67 -0
  237. package/contracts/insured-bridge/avm/Arbitrum_Messenger.sol +72 -0
  238. package/contracts/insured-bridge/interfaces/BridgeAdminInterface.sol +44 -0
  239. package/contracts/insured-bridge/interfaces/BridgePoolInterface.sol +14 -0
  240. package/contracts/insured-bridge/interfaces/MessengerInterface.sol +18 -0
  241. package/contracts/insured-bridge/ovm/OVM_BridgeDepositBox.sol +135 -0
  242. package/contracts/insured-bridge/ovm/OVM_CrossDomainEnabled.sol +84 -0
  243. package/contracts/insured-bridge/ovm/OVM_OETH_BridgeDepositBox.sol +89 -0
  244. package/contracts/insured-bridge/ovm/Optimism_Messenger.sol +34 -0
  245. package/contracts/insured-bridge/ovm/Optimism_Wrapper.sol +59 -0
  246. package/contracts/insured-bridge/ovm/iOVM_CrossDomainMessenger.sol +41 -0
  247. package/contracts/insured-bridge/test/Arbitrum_InboxMock.sol +50 -0
  248. package/contracts/insured-bridge/test/BridgeDepositBoxMock.sol +113 -0
  249. package/contracts/insured-bridge/test/MessengerMock.sol +32 -0
  250. package/contracts/insured-bridge/test/OVM_L1CrossDomainMessengerMock.sol +16 -0
  251. package/contracts/oracle/implementation/Constants.sol +29 -0
  252. package/contracts/oracle/interfaces/FinderInterface.sol +22 -0
  253. package/contracts/oracle/interfaces/IdentifierWhitelistInterface.sol +28 -0
  254. package/contracts/oracle/interfaces/OptimisticOracleInterface.sol +263 -0
  255. package/contracts/oracle/interfaces/SkinnyOptimisticOracleInterface.sol +251 -0
  256. package/contracts/oracle/interfaces/StoreInterface.sol +46 -0
  257. package/package.json +60 -0
@@ -0,0 +1,980 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ pragma solidity ^0.8.0;
3
+
4
+ import "./interfaces/BridgeAdminInterface.sol";
5
+ import "./interfaces/BridgePoolInterface.sol";
6
+
7
+ import "../oracle/interfaces/SkinnyOptimisticOracleInterface.sol";
8
+ import "../oracle/interfaces/StoreInterface.sol";
9
+ import "../oracle/interfaces/FinderInterface.sol";
10
+ import "../oracle/implementation/Constants.sol";
11
+
12
+ import "../common/implementation/AncillaryData.sol";
13
+ import "../common/implementation/Testable.sol";
14
+ import "../common/implementation/FixedPoint.sol";
15
+ import "../common/implementation/Lockable.sol";
16
+ import "../common/implementation/MultiCaller.sol";
17
+
18
+ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
19
+ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
20
+ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
21
+ import "@openzeppelin/contracts/utils/Address.sol";
22
+
23
+ interface WETH9Like {
24
+ function withdraw(uint256 wad) external;
25
+
26
+ function deposit() external payable;
27
+ }
28
+
29
+ /**
30
+ * @notice Contract deployed on L1 that provides methods for "Relayers" to fulfill deposit orders that originated on L2.
31
+ * The Relayers can either post capital to fulfill the deposit (instant relay), or request that the funds are taken out
32
+ * of a passive liquidity provider pool following a challenge period (slow relay). This contract ingests liquidity from
33
+ * passive liquidity providers and returns them claims to withdraw their funds. Liquidity providers are incentivized
34
+ * to post collateral by earning a fee per fulfilled deposit order.
35
+ * @dev A "Deposit" is an order to send capital from L2 to L1, and a "Relay" is a fulfillment attempt of that order.
36
+ */
37
+ contract BridgePool is MultiCaller, Testable, BridgePoolInterface, ERC20, Lockable {
38
+ using SafeERC20 for IERC20;
39
+ using FixedPoint for FixedPoint.Unsigned;
40
+ using Address for address;
41
+
42
+ // Token that this contract receives as LP deposits.
43
+ IERC20 public override l1Token;
44
+
45
+ // Track the total number of relays and uniquely identifies relays.
46
+ uint32 public numberOfRelays;
47
+
48
+ // Reserves that are unutilized and withdrawable.
49
+ uint256 public liquidReserves;
50
+
51
+ // Reserves currently utilized due to L2-L1 transactions in flight.
52
+ int256 public utilizedReserves;
53
+
54
+ // Reserves that are not yet utilized but are pre-allocated for a pending relay.
55
+ uint256 public pendingReserves;
56
+
57
+ // True If this pool stores WETH. If the withdrawn token is WETH then unwrap and send ETH when finalizing
58
+ // relays. Also enable LPs to receive ETH, if they choose, when withdrawing liquidity.
59
+ bool public isWethPool;
60
+
61
+ // Enables the Bridge Admin to enable/disable relays in this pool. Disables relayDeposit and relayAndSpeedUp.
62
+ bool public relaysEnabled = true;
63
+
64
+ // Exponential decay exchange rate to accumulate fees to LPs over time. This can be changed via the BridgeAdmin.
65
+ uint64 public lpFeeRatePerSecond;
66
+
67
+ // Last timestamp that LP fees were updated.
68
+ uint32 public lastLpFeeUpdate;
69
+
70
+ // Store local instances of contract params to save gas relaying.
71
+ uint64 public proposerBondPct;
72
+ uint32 public optimisticOracleLiveness;
73
+
74
+ // Store local instance of the reserve currency final fee. This is a gas optimization to not re-call the store.
75
+ uint256 l1TokenFinalFee;
76
+
77
+ // Cumulative undistributed LP fees. As fees accumulate, they are subtracted from this number.
78
+ uint256 public undistributedLpFees;
79
+
80
+ // Total bond amount held for pending relays. Bonds are released following a successful relay or after a dispute.
81
+ uint256 public bonds;
82
+
83
+ // Administrative contract that deployed this contract and also houses all state variables needed to relay deposits.
84
+ BridgeAdminInterface public bridgeAdmin;
85
+
86
+ // Store local instances of the contract instances to save gas relaying. Can be sync with the Finder at any time via
87
+ // the syncUmaEcosystemParams() public function.
88
+ StoreInterface public store;
89
+ SkinnyOptimisticOracleInterface public optimisticOracle;
90
+
91
+ // DVM price request identifier that is resolved based on the validity of a relay attempt.
92
+ bytes32 public identifier;
93
+
94
+ // A Relay represents an attempt to finalize a cross-chain transfer that originated on an L2 DepositBox contract.
95
+ // The flow chart between states is as follows:
96
+ // - Begin at Uninitialized.
97
+ // - When relayDeposit() is called, a new relay is created with state Pending and mapped to the L2 deposit hash.
98
+ // - If the relay is disputed, the RelayData gets deleted and the L2 deposit hash has no relay mapped to it anymore.
99
+ // - The above statements enable state to transfer between the Uninitialized and Pending states.
100
+ // - When settleRelay() is successfully called, the relay state gets set to Finalized and cannot change from there.
101
+ // - It is impossible for a relay to be deleted when in Finalized state (and have its state set to Uninitialized)
102
+ // because the only way for settleRelay() to succeed is if the price has resolved on the OptimisticOracle.
103
+ // - You cannot dispute an already resolved request on the OptimisticOracle. Moreover, the mapping from
104
+ // a relay's ancillary data hash to its deposit hash is deleted after a successful settleRelay() call.
105
+ enum RelayState { Uninitialized, Pending, Finalized }
106
+
107
+ // Data from L2 deposit transaction.
108
+ struct DepositData {
109
+ uint256 chainId;
110
+ uint64 depositId;
111
+ address payable l1Recipient;
112
+ address l2Sender;
113
+ uint256 amount;
114
+ uint64 slowRelayFeePct;
115
+ uint64 instantRelayFeePct;
116
+ uint32 quoteTimestamp;
117
+ }
118
+
119
+ // Each L2 Deposit can have one Relay attempt at any one time. A Relay attempt is characterized by its RelayData.
120
+ struct RelayData {
121
+ RelayState relayState;
122
+ address slowRelayer;
123
+ uint32 relayId;
124
+ uint64 realizedLpFeePct;
125
+ uint32 priceRequestTime;
126
+ uint256 proposerBond;
127
+ uint256 finalFee;
128
+ }
129
+
130
+ // Associate deposits with pending relay data. When the mapped relay hash is empty, new relay attempts can be made
131
+ // for this deposit. The relay data contains information necessary to pay out relayers on successful relay.
132
+ // Relay hashes are deleted when they are disputed on the OptimisticOracle.
133
+ mapping(bytes32 => bytes32) public relays;
134
+
135
+ // Map hash of deposit and realized-relay fee to instant relayers. This mapping is checked at settlement time
136
+ // to determine if there was a valid instant relayer.
137
+ mapping(bytes32 => address) public instantRelays;
138
+
139
+ event LiquidityAdded(uint256 amount, uint256 lpTokensMinted, address indexed liquidityProvider);
140
+ event LiquidityRemoved(uint256 amount, uint256 lpTokensBurnt, address indexed liquidityProvider);
141
+ event DepositRelayed(
142
+ bytes32 indexed depositHash,
143
+ DepositData depositData,
144
+ RelayData relay,
145
+ bytes32 relayAncillaryDataHash
146
+ );
147
+ event RelaySpedUp(bytes32 indexed depositHash, address indexed instantRelayer, RelayData relay);
148
+
149
+ // Note: the difference between a dispute and a cancellation is that a cancellation happens in the case where
150
+ // something changes in the OO between request and dispute that causes calls to it to fail. The most common
151
+ // case would be an increase in final fee. However, things like whitelisting can also cause problems.
152
+ event RelayDisputed(bytes32 indexed depositHash, bytes32 indexed relayHash, address indexed disputer);
153
+ event RelayCanceled(bytes32 indexed depositHash, bytes32 indexed relayHash, address indexed disputer);
154
+ event RelaySettled(bytes32 indexed depositHash, address indexed caller, RelayData relay);
155
+ event BridgePoolAdminTransferred(address oldAdmin, address newAdmin);
156
+ event RelaysEnabledSet(bool newRelaysEnabled);
157
+ event LpFeeRateSet(uint64 newLpFeeRatePerSecond);
158
+
159
+ modifier onlyBridgeAdmin() {
160
+ require(msg.sender == address(bridgeAdmin), "Caller not bridge admin");
161
+ _;
162
+ }
163
+
164
+ modifier onlyIfRelaysEnabld() {
165
+ require(relaysEnabled, "Relays are disabled");
166
+ _;
167
+ }
168
+
169
+ /**
170
+ * @notice Construct the Bridge Pool.
171
+ * @param _lpTokenName Name of the LP token to be deployed by this contract.
172
+ * @param _lpTokenSymbol Symbol of the LP token to be deployed by this contract.
173
+ * @param _bridgeAdmin Admin contract deployed alongside on L1. Stores global variables and has owner control.
174
+ * @param _l1Token Address of the L1 token that this bridgePool holds. This is the token LPs deposit and is bridged.
175
+ * @param _lpFeeRatePerSecond Interest rate payment that scales the amount of pending fees per second paid to LPs.
176
+ * @param _isWethPool Toggles if this is the WETH pool. If it is then can accept ETH and wrap to WETH for the user.
177
+ * @param _timer Timer used to synchronize contract time in testing. Set to 0x000... in production.
178
+ */
179
+ constructor(
180
+ string memory _lpTokenName,
181
+ string memory _lpTokenSymbol,
182
+ address _bridgeAdmin,
183
+ address _l1Token,
184
+ uint64 _lpFeeRatePerSecond,
185
+ bool _isWethPool,
186
+ address _timer
187
+ ) Testable(_timer) ERC20(_lpTokenName, _lpTokenSymbol) {
188
+ require(bytes(_lpTokenName).length != 0 && bytes(_lpTokenSymbol).length != 0, "Bad LP token name or symbol");
189
+ bridgeAdmin = BridgeAdminInterface(_bridgeAdmin);
190
+ l1Token = IERC20(_l1Token);
191
+ lastLpFeeUpdate = uint32(getCurrentTime());
192
+ lpFeeRatePerSecond = _lpFeeRatePerSecond;
193
+ isWethPool = _isWethPool;
194
+
195
+ syncUmaEcosystemParams(); // Fetch OptimisticOracle and Store addresses and L1Token finalFee.
196
+ syncWithBridgeAdminParams(); // Fetch ProposerBondPct OptimisticOracleLiveness, Identifier from the BridgeAdmin.
197
+
198
+ emit LpFeeRateSet(lpFeeRatePerSecond);
199
+ }
200
+
201
+ /*************************************************
202
+ * LIQUIDITY PROVIDER FUNCTIONS *
203
+ *************************************************/
204
+
205
+ /**
206
+ * @notice Add liquidity to the bridge pool. Pulls l1Token from the caller's wallet. The caller is sent back a
207
+ * commensurate number of LP tokens (minted to their address) at the prevailing exchange rate.
208
+ * @dev The caller must approve this contract to transfer `l1TokenAmount` amount of l1Token if depositing ERC20.
209
+ * @dev The caller can deposit ETH which is auto wrapped to WETH. This can only be done if: a) this is the Weth pool
210
+ * and b) the l1TokenAmount matches to the transaction msg.value.
211
+ * @dev Reentrancy guard not added to this function because this indirectly calls sync() which is guarded.
212
+ * @param l1TokenAmount Number of l1Token to add as liquidity.
213
+ */
214
+ function addLiquidity(uint256 l1TokenAmount) public payable nonReentrant() {
215
+ // If this is the weth pool and the caller sends msg.value then the msg.value must match the l1TokenAmount.
216
+ // Else, msg.value must be set to 0.
217
+ require((isWethPool && msg.value == l1TokenAmount) || msg.value == 0, "Bad add liquidity Eth value");
218
+
219
+ // Since `exchangeRateCurrent()` reads this contract's balance and updates contract state using it,
220
+ // we must call it first before transferring any tokens to this contract.
221
+ uint256 lpTokensToMint = (l1TokenAmount * 1e18) / _exchangeRateCurrent();
222
+ _mint(msg.sender, lpTokensToMint);
223
+ liquidReserves += l1TokenAmount;
224
+
225
+ if (msg.value > 0 && isWethPool) WETH9Like(address(l1Token)).deposit{ value: msg.value }();
226
+ else l1Token.safeTransferFrom(msg.sender, address(this), l1TokenAmount);
227
+
228
+ emit LiquidityAdded(l1TokenAmount, lpTokensToMint, msg.sender);
229
+ }
230
+
231
+ /**
232
+ * @notice Removes liquidity from the bridge pool. Burns lpTokenAmount LP tokens from the caller's wallet. The caller
233
+ * is sent back a commensurate number of l1Tokens at the prevailing exchange rate.
234
+ * @dev The caller does not need to approve the spending of LP tokens as this method directly uses the burn logic.
235
+ * @dev Reentrancy guard not added to this function because this indirectly calls sync() which is guarded.
236
+ * @param lpTokenAmount Number of lpTokens to redeem for underlying.
237
+ * @param sendEth Enable the liquidity provider to remove liquidity in ETH, if this is the WETH pool.
238
+ */
239
+ function removeLiquidity(uint256 lpTokenAmount, bool sendEth) public nonReentrant() {
240
+ // Can only send eth on withdrawing liquidity iff this is the WETH pool.
241
+ require(!sendEth || isWethPool, "Cant send eth");
242
+ uint256 l1TokensToReturn = (lpTokenAmount * _exchangeRateCurrent()) / 1e18;
243
+
244
+ // Check that there is enough liquid reserves to withdraw the requested amount.
245
+ require(liquidReserves >= (pendingReserves + l1TokensToReturn), "Utilization too high to remove");
246
+
247
+ _burn(msg.sender, lpTokenAmount);
248
+ liquidReserves -= l1TokensToReturn;
249
+
250
+ if (sendEth) _unwrapWETHTo(payable(msg.sender), l1TokensToReturn);
251
+ else l1Token.safeTransfer(msg.sender, l1TokensToReturn);
252
+
253
+ emit LiquidityRemoved(l1TokensToReturn, lpTokenAmount, msg.sender);
254
+ }
255
+
256
+ /**************************************
257
+ * RELAYER FUNCTIONS *
258
+ **************************************/
259
+
260
+ /**
261
+ * @notice Called by Relayer to execute a slow + fast relay from L2 to L1, fulfilling a corresponding deposit order.
262
+ * @dev There can only be one pending relay for a deposit. This method is effectively the relayDeposit and
263
+ * speedUpRelay methods concatenated. This could be refactored to just call each method, but there
264
+ * are some gas savings in combining the transfers and hash computations.
265
+ * @dev Caller must have approved this contract to spend the total bond + amount - fees for `l1Token`.
266
+ * @dev This function can only be called if relays are enabled for this bridge pool.
267
+ * @param depositData the deposit data struct containing all the user's deposit information.
268
+ * @param realizedLpFeePct LP fee calculated off-chain considering the L1 pool liquidity at deposit time, before
269
+ * quoteTimestamp. The OO acts to verify the correctness of this realized fee. Cannot exceed 50%.
270
+ */
271
+ function relayAndSpeedUp(DepositData memory depositData, uint64 realizedLpFeePct)
272
+ public
273
+ onlyIfRelaysEnabld()
274
+ nonReentrant()
275
+ {
276
+ // If no pending relay for this deposit, then associate the caller's relay attempt with it.
277
+ uint32 priceRequestTime = uint32(getCurrentTime());
278
+
279
+ // The realizedLPFeePct should never be greater than 0.5e18 and the slow and instant relay fees should never be
280
+ // more than 0.25e18 each. Therefore, the sum of all fee types can never exceed 1e18 (or 100%).
281
+ require(
282
+ depositData.slowRelayFeePct <= 0.25e18 &&
283
+ depositData.instantRelayFeePct <= 0.25e18 &&
284
+ realizedLpFeePct <= 0.5e18,
285
+ "Invalid fees"
286
+ );
287
+
288
+ // Check if there is a pending relay for this deposit.
289
+ bytes32 depositHash = _getDepositHash(depositData);
290
+
291
+ // Note: A disputed relay deletes the stored relay hash and enables this require statement to pass.
292
+ require(relays[depositHash] == bytes32(0), "Pending relay exists");
293
+
294
+ uint256 proposerBond = _getProposerBond(depositData.amount);
295
+
296
+ // Save hash of new relay attempt parameters.
297
+ // Note: The liveness for this relay can be changed in the BridgeAdmin, which means that each relay has a
298
+ // potentially variable liveness time. This should not provide any exploit opportunities, especially because
299
+ // the BridgeAdmin state (including the liveness value) is permissioned to the cross domained owner.
300
+ RelayData memory relayData =
301
+ RelayData({
302
+ relayState: RelayState.Pending,
303
+ slowRelayer: msg.sender,
304
+ relayId: numberOfRelays++, // Note: Increment numberOfRelays at the same time as setting relayId to its current value.
305
+ realizedLpFeePct: realizedLpFeePct,
306
+ priceRequestTime: priceRequestTime,
307
+ proposerBond: proposerBond,
308
+ finalFee: l1TokenFinalFee
309
+ });
310
+ bytes32 relayHash = _getRelayHash(depositData, relayData);
311
+ relays[depositHash] = _getRelayDataHash(relayData);
312
+
313
+ bytes32 instantRelayHash = _getInstantRelayHash(depositHash, relayData);
314
+ require(
315
+ // Can only speed up a pending relay without an existing instant relay associated with it.
316
+ instantRelays[instantRelayHash] == address(0),
317
+ "Relay cannot be sped up"
318
+ );
319
+
320
+ // Sanity check that pool has enough balance to cover relay amount + proposer reward. Reward amount will be
321
+ // paid on settlement after the OptimisticOracle price request has passed the challenge period.
322
+ // Note: liquidReserves should always be <= balance - bonds.
323
+ require(liquidReserves - pendingReserves >= depositData.amount, "Insufficient pool balance");
324
+
325
+ // Compute total proposal bond and pull from caller so that the OptimisticOracle can pull it from here.
326
+ uint256 totalBond = proposerBond + l1TokenFinalFee;
327
+
328
+ // Pull relay amount minus fees from caller and send to the deposit l1Recipient. The total fees paid is the sum
329
+ // of the LP fees, the relayer fees and the instant relay fee.
330
+ uint256 feesTotal =
331
+ _getAmountFromPct(
332
+ relayData.realizedLpFeePct + depositData.slowRelayFeePct + depositData.instantRelayFeePct,
333
+ depositData.amount
334
+ );
335
+ // If the L1 token is WETH then: a) pull WETH from instant relayer b) unwrap WETH c) send ETH to recipient.
336
+ uint256 recipientAmount = depositData.amount - feesTotal;
337
+
338
+ bonds += totalBond;
339
+ pendingReserves += depositData.amount; // Book off maximum liquidity used by this relay in the pending reserves.
340
+
341
+ instantRelays[instantRelayHash] = msg.sender;
342
+
343
+ l1Token.safeTransferFrom(msg.sender, address(this), recipientAmount + totalBond);
344
+
345
+ // If this is a weth pool then unwrap and send eth.
346
+ if (isWethPool) {
347
+ _unwrapWETHTo(depositData.l1Recipient, recipientAmount);
348
+ // Else, this is a normal ERC20 token. Send to recipient.
349
+ } else l1Token.safeTransfer(depositData.l1Recipient, recipientAmount);
350
+
351
+ emit DepositRelayed(depositHash, depositData, relayData, relayHash);
352
+ emit RelaySpedUp(depositHash, msg.sender, relayData);
353
+ }
354
+
355
+ /**
356
+ * @notice Called by Disputer to dispute an ongoing relay.
357
+ * @dev The result of this method is to always throw out the relay, providing an opportunity for another relay for
358
+ * the same deposit. Between the disputer and proposer, whoever is incorrect loses their bond. Whoever is correct
359
+ * gets it back + a payout.
360
+ * @dev Caller must have approved this contract to spend the total bond + amount - fees for `l1Token`.
361
+ * @param depositData the deposit data struct containing all the user's deposit information.
362
+ * @param relayData RelayData logged in the disputed relay.
363
+ */
364
+ function disputeRelay(DepositData memory depositData, RelayData memory relayData) public nonReentrant() {
365
+ require(relayData.priceRequestTime + optimisticOracleLiveness > getCurrentTime(), "Past liveness");
366
+ require(relayData.relayState == RelayState.Pending, "Not disputable");
367
+ // Validate the input data.
368
+ bytes32 depositHash = _getDepositHash(depositData);
369
+ _validateRelayDataHash(depositHash, relayData);
370
+
371
+ // Submit the proposal and dispute to the OO.
372
+ bytes32 relayHash = _getRelayHash(depositData, relayData);
373
+
374
+ // Note: in some cases this will fail due to changes in the OO and the method will refund the relayer.
375
+ bool success =
376
+ _requestProposeDispute(
377
+ relayData.slowRelayer,
378
+ msg.sender,
379
+ relayData.proposerBond,
380
+ relayData.finalFee,
381
+ _getRelayAncillaryData(relayHash)
382
+ );
383
+
384
+ // Drop the relay and remove the bond from the tracked bonds.
385
+ bonds -= relayData.finalFee + relayData.proposerBond;
386
+ pendingReserves -= depositData.amount;
387
+ delete relays[depositHash];
388
+ if (success) emit RelayDisputed(depositHash, _getRelayDataHash(relayData), msg.sender);
389
+ else emit RelayCanceled(depositHash, _getRelayDataHash(relayData), msg.sender);
390
+ }
391
+
392
+ /**
393
+ * @notice Called by Relayer to execute a slow relay from L2 to L1, fulfilling a corresponding deposit order.
394
+ * @dev There can only be one pending relay for a deposit.
395
+ * @dev Caller must have approved this contract to spend the total bond + amount - fees for `l1Token`.
396
+ * @dev This function can only be called if relays are enabled for this bridge pool.
397
+ * @param depositData the deposit data struct containing all the user's deposit information.
398
+ * @param realizedLpFeePct LP fee calculated off-chain considering the L1 pool liquidity at deposit time, before
399
+ * quoteTimestamp. The OO acts to verify the correctness of this realized fee. Cannot exceed 50%.
400
+ */
401
+ function relayDeposit(DepositData memory depositData, uint64 realizedLpFeePct)
402
+ public
403
+ onlyIfRelaysEnabld()
404
+ nonReentrant()
405
+ {
406
+ // The realizedLPFeePct should never be greater than 0.5e18 and the slow and instant relay fees should never be
407
+ // more than 0.25e18 each. Therefore, the sum of all fee types can never exceed 1e18 (or 100%).
408
+ require(
409
+ depositData.slowRelayFeePct <= 0.25e18 &&
410
+ depositData.instantRelayFeePct <= 0.25e18 &&
411
+ realizedLpFeePct <= 0.5e18,
412
+ "Invalid fees"
413
+ );
414
+
415
+ // Check if there is a pending relay for this deposit.
416
+ bytes32 depositHash = _getDepositHash(depositData);
417
+
418
+ // Note: A disputed relay deletes the stored relay hash and enables this require statement to pass.
419
+ require(relays[depositHash] == bytes32(0), "Pending relay exists");
420
+
421
+ // If no pending relay for this deposit, then associate the caller's relay attempt with it.
422
+ uint32 priceRequestTime = uint32(getCurrentTime());
423
+
424
+ uint256 proposerBond = _getProposerBond(depositData.amount);
425
+
426
+ // Save hash of new relay attempt parameters.
427
+ // Note: The liveness for this relay can be changed in the BridgeAdmin, which means that each relay has a
428
+ // potentially variable liveness time. This should not provide any exploit opportunities, especially because
429
+ // the BridgeAdmin state (including the liveness value) is permissioned to the cross domained owner.
430
+ RelayData memory relayData =
431
+ RelayData({
432
+ relayState: RelayState.Pending,
433
+ slowRelayer: msg.sender,
434
+ relayId: numberOfRelays++, // Note: Increment numberOfRelays at the same time as setting relayId to its current value.
435
+ realizedLpFeePct: realizedLpFeePct,
436
+ priceRequestTime: priceRequestTime,
437
+ proposerBond: proposerBond,
438
+ finalFee: l1TokenFinalFee
439
+ });
440
+ relays[depositHash] = _getRelayDataHash(relayData);
441
+
442
+ bytes32 relayHash = _getRelayHash(depositData, relayData);
443
+
444
+ // Sanity check that pool has enough balance to cover relay amount + proposer reward. Reward amount will be
445
+ // paid on settlement after the OptimisticOracle price request has passed the challenge period.
446
+ // Note: liquidReserves should always be <= balance - bonds.
447
+ require(liquidReserves - pendingReserves >= depositData.amount, "Insufficient pool balance");
448
+
449
+ // Compute total proposal bond and pull from caller so that the OptimisticOracle can pull it from here.
450
+ uint256 totalBond = proposerBond + l1TokenFinalFee;
451
+ pendingReserves += depositData.amount; // Book off maximum liquidity used by this relay in the pending reserves.
452
+ bonds += totalBond;
453
+
454
+ l1Token.safeTransferFrom(msg.sender, address(this), totalBond);
455
+ emit DepositRelayed(depositHash, depositData, relayData, relayHash);
456
+ }
457
+
458
+ /**
459
+ * @notice Instantly relay a deposit amount minus fees to the l1Recipient. Instant relayer earns a reward following
460
+ * the pending relay challenge period.
461
+ * @dev We assume that the caller has performed an off-chain check that the deposit data they are attempting to
462
+ * relay is valid. If the deposit data is invalid, then the instant relayer has no recourse to receive their funds
463
+ * back after the invalid deposit data is disputed. Moreover, no one will be able to resubmit a relay for the
464
+ * invalid deposit data because they know it will get disputed again. On the other hand, if the deposit data is
465
+ * valid, then even if it is falsely disputed, the instant relayer will eventually get reimbursed because someone
466
+ * else will be incentivized to resubmit the relay to earn slow relayer rewards. Once the valid relay is finalized,
467
+ * the instant relayer will be reimbursed. Therefore, the caller has the same responsibility as the disputer in
468
+ * validating the relay data.
469
+ * @dev Caller must have approved this contract to spend the deposit amount of L1 tokens to relay. There can only
470
+ * be one instant relayer per relay attempt. You cannot speed up a relay that is past liveness.
471
+ * @param depositData Unique set of L2 deposit data that caller is trying to instantly relay.
472
+ * @param relayData Parameters of Relay that caller is attempting to speedup. Must hash to the stored relay hash
473
+ * for this deposit or this method will revert.
474
+ */
475
+ function speedUpRelay(DepositData memory depositData, RelayData memory relayData) public nonReentrant() {
476
+ bytes32 depositHash = _getDepositHash(depositData);
477
+ _validateRelayDataHash(depositHash, relayData);
478
+ bytes32 instantRelayHash = _getInstantRelayHash(depositHash, relayData);
479
+ require(
480
+ // Can only speed up a pending relay without an existing instant relay associated with it.
481
+ getCurrentTime() < relayData.priceRequestTime + optimisticOracleLiveness &&
482
+ relayData.relayState == RelayState.Pending &&
483
+ instantRelays[instantRelayHash] == address(0),
484
+ "Relay cannot be sped up"
485
+ );
486
+ instantRelays[instantRelayHash] = msg.sender;
487
+
488
+ // Pull relay amount minus fees from caller and send to the deposit l1Recipient. The total fees paid is the sum
489
+ // of the LP fees, the relayer fees and the instant relay fee.
490
+ uint256 feesTotal =
491
+ _getAmountFromPct(
492
+ relayData.realizedLpFeePct + depositData.slowRelayFeePct + depositData.instantRelayFeePct,
493
+ depositData.amount
494
+ );
495
+ // If the L1 token is WETH then: a) pull WETH from instant relayer b) unwrap WETH c) send ETH to recipient.
496
+ uint256 recipientAmount = depositData.amount - feesTotal;
497
+ if (isWethPool) {
498
+ l1Token.safeTransferFrom(msg.sender, address(this), recipientAmount);
499
+ _unwrapWETHTo(depositData.l1Recipient, recipientAmount);
500
+ // Else, this is a normal ERC20 token. Send to recipient.
501
+ } else l1Token.safeTransferFrom(msg.sender, depositData.l1Recipient, recipientAmount);
502
+
503
+ emit RelaySpedUp(depositHash, msg.sender, relayData);
504
+ }
505
+
506
+ /**
507
+ * @notice Reward relayers if a pending relay price request has a price available on the OptimisticOracle. Mark
508
+ * the relay as complete.
509
+ * @dev We use the relayData and depositData to compute the ancillary data that the relay price request is uniquely
510
+ * associated with on the OptimisticOracle. If the price request passed in does not match the pending relay price
511
+ * request, then this will revert.
512
+ * @param depositData Unique set of L2 deposit data that caller is trying to settle a relay for.
513
+ * @param relayData Parameters of Relay that caller is attempting to settle. Must hash to the stored relay hash
514
+ * for this deposit.
515
+ */
516
+ function settleRelay(DepositData memory depositData, RelayData memory relayData) public nonReentrant() {
517
+ bytes32 depositHash = _getDepositHash(depositData);
518
+ _validateRelayDataHash(depositHash, relayData);
519
+ require(relayData.relayState == RelayState.Pending, "Already settled");
520
+ uint32 expirationTime = relayData.priceRequestTime + optimisticOracleLiveness;
521
+ require(expirationTime <= getCurrentTime(), "Not settleable yet");
522
+
523
+ // Note: this check is to give the relayer a small, but reasonable amount of time to complete the relay before
524
+ // before it can be "stolen" by someone else. This is to ensure there is an incentive to settle relays quickly.
525
+ require(
526
+ msg.sender == relayData.slowRelayer || getCurrentTime() > expirationTime + 15 minutes,
527
+ "Not slow relayer"
528
+ );
529
+
530
+ // Update the relay state to Finalized. This prevents any re-settling of a relay.
531
+ relays[depositHash] = _getRelayDataHash(
532
+ RelayData({
533
+ relayState: RelayState.Finalized,
534
+ slowRelayer: relayData.slowRelayer,
535
+ relayId: relayData.relayId,
536
+ realizedLpFeePct: relayData.realizedLpFeePct,
537
+ priceRequestTime: relayData.priceRequestTime,
538
+ proposerBond: relayData.proposerBond,
539
+ finalFee: relayData.finalFee
540
+ })
541
+ );
542
+
543
+ // Reward relayers and pay out l1Recipient.
544
+ // At this point there are two possible cases:
545
+ // - This was a slow relay: In this case, a) pay the slow relayer their reward and b) pay the l1Recipient of the
546
+ // amount minus the realized LP fee and the slow Relay fee. The transfer was not sped up so no instant fee.
547
+ // - This was an instant relay: In this case, a) pay the slow relayer their reward and b) pay the instant relayer
548
+ // the full bridging amount, minus the realized LP fee and minus the slow relay fee. When the instant
549
+ // relayer called speedUpRelay they were docked this same amount, minus the instant relayer fee. As a
550
+ // result, they are effectively paid what they spent when speeding up the relay + the instantRelayFee.
551
+
552
+ uint256 instantRelayerOrRecipientAmount =
553
+ depositData.amount -
554
+ _getAmountFromPct(relayData.realizedLpFeePct + depositData.slowRelayFeePct, depositData.amount);
555
+
556
+ // Refund the instant relayer iff the instant relay params match the approved relay.
557
+ bytes32 instantRelayHash = _getInstantRelayHash(depositHash, relayData);
558
+ address instantRelayer = instantRelays[instantRelayHash];
559
+
560
+ // If this is the WETH pool and the instant relayer is is address 0x0 (i.e the relay was not sped up) then:
561
+ // a) withdraw WETH to ETH and b) send the ETH to the recipient.
562
+ if (isWethPool && instantRelayer == address(0)) {
563
+ _unwrapWETHTo(depositData.l1Recipient, instantRelayerOrRecipientAmount);
564
+ // Else, this is a normal slow relay being finalizes where the contract sends ERC20 to the recipient OR this
565
+ // is the finalization of an instant relay where we need to reimburse the instant relayer in WETH.
566
+ } else
567
+ l1Token.safeTransfer(
568
+ instantRelayer != address(0) ? instantRelayer : depositData.l1Recipient,
569
+ instantRelayerOrRecipientAmount
570
+ );
571
+
572
+ // There is a fee and a bond to pay out. The fee goes to whoever settles. The bond always goes back to the
573
+ // slow relayer.
574
+ // Note: for gas efficiency, we use an if so we can combine these transfers in the event that they are the same
575
+ // address.
576
+ uint256 slowRelayerReward = _getAmountFromPct(depositData.slowRelayFeePct, depositData.amount);
577
+ uint256 totalBond = relayData.finalFee + relayData.proposerBond;
578
+ if (relayData.slowRelayer == msg.sender)
579
+ l1Token.safeTransfer(relayData.slowRelayer, slowRelayerReward + totalBond);
580
+ else {
581
+ l1Token.safeTransfer(relayData.slowRelayer, totalBond);
582
+ l1Token.safeTransfer(msg.sender, slowRelayerReward);
583
+ }
584
+
585
+ uint256 totalReservesSent = instantRelayerOrRecipientAmount + slowRelayerReward;
586
+
587
+ // Update reserves by amounts changed and allocated LP fees.
588
+ pendingReserves -= depositData.amount;
589
+ liquidReserves -= totalReservesSent;
590
+ utilizedReserves += int256(totalReservesSent);
591
+ bonds -= totalBond;
592
+ _updateAccumulatedLpFees();
593
+ _allocateLpFees(_getAmountFromPct(relayData.realizedLpFeePct, depositData.amount));
594
+
595
+ emit RelaySettled(depositHash, msg.sender, relayData);
596
+
597
+ // Clean up state storage and receive gas refund. This also prevents `priceDisputed()` from being able to reset
598
+ // this newly Finalized relay state.
599
+ delete instantRelays[instantRelayHash];
600
+ }
601
+
602
+ /**
603
+ * @notice Synchronize any balance changes in this contract with the utilized & liquid reserves. This would be done
604
+ * at the conclusion of an L2 -> L1 token transfer via the canonical token bridge.
605
+ */
606
+ function sync() public nonReentrant() {
607
+ _sync();
608
+ }
609
+
610
+ /**
611
+ * @notice Computes the exchange rate between LP tokens and L1Tokens. Used when adding/removing liquidity.
612
+ * @return The updated exchange rate between LP tokens and L1 tokens.
613
+ */
614
+ function exchangeRateCurrent() public nonReentrant() returns (uint256) {
615
+ return _exchangeRateCurrent();
616
+ }
617
+
618
+ /**
619
+ * @notice Computes the current liquidity utilization ratio.
620
+ * @dev Used in computing realizedLpFeePct off-chain.
621
+ * @return The current utilization ratio.
622
+ */
623
+ function liquidityUtilizationCurrent() public nonReentrant() returns (uint256) {
624
+ return _liquidityUtilizationPostRelay(0);
625
+ }
626
+
627
+ /**
628
+ * @notice Computes the liquidity utilization ratio post a relay of known size.
629
+ * @dev Used in computing realizedLpFeePct off-chain.
630
+ * @param relayedAmount Size of the relayed deposit to factor into the utilization calculation.
631
+ * @return The updated utilization ratio accounting for a new `relayedAmount`.
632
+ */
633
+ function liquidityUtilizationPostRelay(uint256 relayedAmount) public nonReentrant() returns (uint256) {
634
+ return _liquidityUtilizationPostRelay(relayedAmount);
635
+ }
636
+
637
+ /**
638
+ * @notice Return both the current utilization value and liquidity utilization post the relay.
639
+ * @dev Used in computing realizedLpFeePct off-chain.
640
+ * @param relayedAmount Size of the relayed deposit to factor into the utilization calculation.
641
+ * @return utilizationCurrent The current utilization ratio.
642
+ * @return utilizationPostRelay The updated utilization ratio accounting for a new `relayedAmount`.
643
+ */
644
+ function getLiquidityUtilization(uint256 relayedAmount)
645
+ public
646
+ nonReentrant()
647
+ returns (uint256 utilizationCurrent, uint256 utilizationPostRelay)
648
+ {
649
+ return (_liquidityUtilizationPostRelay(0), _liquidityUtilizationPostRelay(relayedAmount));
650
+ }
651
+
652
+ /**
653
+ * @notice Updates the address stored in this contract for the OptimisticOracle and the Store to the latest versions
654
+ * set in the the Finder. Also pull finalFee Store these as local variables to make relay methods gas efficient.
655
+ * @dev There is no risk of leaving this function public for anyone to call as in all cases we want the addresses
656
+ * in this contract to map to the latest version in the Finder and store the latest final fee.
657
+ */
658
+ function syncUmaEcosystemParams() public nonReentrant() {
659
+ FinderInterface finder = FinderInterface(bridgeAdmin.finder());
660
+ optimisticOracle = SkinnyOptimisticOracleInterface(
661
+ finder.getImplementationAddress(OracleInterfaces.SkinnyOptimisticOracle)
662
+ );
663
+
664
+ store = StoreInterface(finder.getImplementationAddress(OracleInterfaces.Store));
665
+ l1TokenFinalFee = store.computeFinalFee(address(l1Token)).rawValue;
666
+ }
667
+
668
+ /**
669
+ * @notice Updates the values of stored constants for the proposerBondPct, optimisticOracleLiveness and identifier
670
+ * to that set in the bridge Admin. We store these as local variables to make the relay methods more gas efficient.
671
+ * @dev There is no risk of leaving this function public for anyone to call as in all cases we want these values
672
+ * in this contract to map to the latest version set in the BridgeAdmin.
673
+ */
674
+ function syncWithBridgeAdminParams() public nonReentrant() {
675
+ proposerBondPct = bridgeAdmin.proposerBondPct();
676
+ optimisticOracleLiveness = bridgeAdmin.optimisticOracleLiveness();
677
+ identifier = bridgeAdmin.identifier();
678
+ }
679
+
680
+ /************************************
681
+ * ADMIN FUNCTIONS *
682
+ ************************************/
683
+
684
+ /**
685
+ * @notice Enable the current bridge admin to transfer admin to to a new address.
686
+ * @dev Caller must be BridgeAdmin contract.
687
+ * @param _newAdmin Admin address of the new admin.
688
+ */
689
+ function changeAdmin(address _newAdmin) public override onlyBridgeAdmin() nonReentrant() {
690
+ bridgeAdmin = BridgeAdminInterface(_newAdmin);
691
+ emit BridgePoolAdminTransferred(msg.sender, _newAdmin);
692
+ }
693
+
694
+ /**
695
+ * @notice Enable the bridge admin to change the decay rate at which LP shares accumulate fees. The higher this
696
+ * value, the faster LP shares realize pending fees.
697
+ * @dev Caller must be BridgeAdmin contract.
698
+ * @param _newLpFeeRatePerSecond The new rate to set.
699
+ */
700
+ function setLpFeeRatePerSecond(uint64 _newLpFeeRatePerSecond) public override onlyBridgeAdmin() nonReentrant() {
701
+ lpFeeRatePerSecond = _newLpFeeRatePerSecond;
702
+ emit LpFeeRateSet(lpFeeRatePerSecond);
703
+ }
704
+
705
+ /**
706
+ * @notice Enable the bridge admin to enable/disable relays for this pool. Acts as a pause. Only effects
707
+ * relayDeposit and relayAndSpeedUp methods. ALl other contract logic remains functional after a pause.
708
+ * @dev Caller must be BridgeAdmin contract.
709
+ * @param _relaysEnabled The new relaysEnabled state.
710
+ */
711
+ function setRelaysEnabled(bool _relaysEnabled) public override onlyBridgeAdmin() nonReentrant() {
712
+ relaysEnabled = _relaysEnabled;
713
+ emit RelaysEnabledSet(_relaysEnabled);
714
+ }
715
+
716
+ /************************************
717
+ * VIEW FUNCTIONS *
718
+ ************************************/
719
+
720
+ /**
721
+ * @notice Computes the current amount of unallocated fees that have accumulated from the previous time this the
722
+ * contract was called.
723
+ */
724
+ function getAccumulatedFees() public view nonReentrantView() returns (uint256) {
725
+ return _getAccumulatedFees();
726
+ }
727
+
728
+ /**
729
+ * @notice Returns ancillary data containing all relevant Relay data that voters can format into UTF8 and use to
730
+ * determine if the relay is valid.
731
+ * @dev Helpful method to test that ancillary data is constructed properly. We should consider removing if we don't
732
+ * anticipate off-chain bots or users to call this method.
733
+ * @param depositData Contains L2 deposit information used by off-chain validators to validate relay.
734
+ * @param relayData Contains relay information used by off-chain validators to validate relay.
735
+ * @return bytes New ancillary data that can be decoded into UTF8.
736
+ */
737
+ function getRelayAncillaryData(DepositData memory depositData, RelayData memory relayData)
738
+ public
739
+ view
740
+ nonReentrantView()
741
+ returns (bytes memory)
742
+ {
743
+ return _getRelayAncillaryData(_getRelayHash(depositData, relayData));
744
+ }
745
+
746
+ /**************************************
747
+ * INTERNAL & PRIVATE FUNCTIONS *
748
+ **************************************/
749
+
750
+ function _liquidityUtilizationPostRelay(uint256 relayedAmount) internal returns (uint256) {
751
+ _sync(); // Fetch any balance changes due to token bridging finalization and factor them in.
752
+
753
+ // liquidityUtilizationRatio :=
754
+ // (relayedAmount + pendingReserves + max(utilizedReserves,0)) / (liquidReserves + max(utilizedReserves,0))
755
+ // UtilizedReserves has a dual meaning: if it's greater than zero then it represents funds pending in the bridge
756
+ // that will flow from L2 to L1. In this case, we can use it normally in the equation. However, if it is
757
+ // negative, then it is already counted in liquidReserves. This occurs if tokens are transferred directly to the
758
+ // contract. In this case, ignore it as it is captured in liquid reserves and has no meaning in the numerator.
759
+ uint256 flooredUtilizedReserves = utilizedReserves > 0 ? uint256(utilizedReserves) : 0;
760
+ uint256 numerator = relayedAmount + pendingReserves + flooredUtilizedReserves;
761
+ uint256 denominator = liquidReserves + flooredUtilizedReserves;
762
+
763
+ // If the denominator equals zero, return 1e18 (max utilization).
764
+ if (denominator == 0) return 1e18;
765
+
766
+ // In all other cases, return the utilization ratio.
767
+ return (numerator * 1e18) / denominator;
768
+ }
769
+
770
+ function _sync() internal {
771
+ // Check if the l1Token balance of the contract is greater than the liquidReserves. If it is then the bridging
772
+ // action from L2 -> L1 has concluded and the local accounting can be updated.
773
+ uint256 l1TokenBalance = l1Token.balanceOf(address(this)) - bonds;
774
+ if (l1TokenBalance > liquidReserves) {
775
+ // utilizedReserves can go to less than zero. This will happen if the accumulated fees exceeds the current
776
+ // outstanding utilization. In other words, if outstanding bridging transfers are 0 then utilizedReserves
777
+ // will equal the total LP fees accumulated over all time.
778
+ utilizedReserves -= int256(l1TokenBalance - liquidReserves);
779
+ liquidReserves = l1TokenBalance;
780
+ }
781
+ }
782
+
783
+ function _exchangeRateCurrent() internal returns (uint256) {
784
+ if (totalSupply() == 0) return 1e18; // initial rate is 1 pre any mint action.
785
+
786
+ // First, update fee counters and local accounting of finalized transfers from L2 -> L1.
787
+ _updateAccumulatedLpFees(); // Accumulate all allocated fees from the last time this method was called.
788
+ _sync(); // Fetch any balance changes due to token bridging finalization and factor them in.
789
+
790
+ // ExchangeRate := (liquidReserves + utilizedReserves - undistributedLpFees) / lpTokenSupply
791
+ // Note that utilizedReserves can be negative. If this is the case, then liquidReserves is offset by an equal
792
+ // and opposite size. LiquidReserves + utilizedReserves will always be larger than undistributedLpFees so this
793
+ // int will always be positive so there is no risk in underflow in type casting in the return line.
794
+ int256 numerator = int256(liquidReserves) + utilizedReserves - int256(undistributedLpFees);
795
+ return (uint256(numerator) * 1e18) / totalSupply();
796
+ }
797
+
798
+ // Return UTF8-decodable ancillary data for relay price request associated with relay hash.
799
+ function _getRelayAncillaryData(bytes32 relayHash) private pure returns (bytes memory) {
800
+ return AncillaryData.appendKeyValueBytes32("", "relayHash", relayHash);
801
+ }
802
+
803
+ // Returns hash of unique relay and deposit event. This is added to the relay request's ancillary data.
804
+ function _getRelayHash(DepositData memory depositData, RelayData memory relayData) private view returns (bytes32) {
805
+ return keccak256(abi.encode(depositData, relayData.relayId, relayData.realizedLpFeePct, address(l1Token)));
806
+ }
807
+
808
+ // Return hash of relay data, which is stored in state and mapped to a deposit hash.
809
+ function _getRelayDataHash(RelayData memory relayData) private pure returns (bytes32) {
810
+ return keccak256(abi.encode(relayData));
811
+ }
812
+
813
+ // Reverts if the stored relay data hash for `depositHash` does not match `_relayData`.
814
+ function _validateRelayDataHash(bytes32 depositHash, RelayData memory relayData) private view {
815
+ require(
816
+ relays[depositHash] == _getRelayDataHash(relayData),
817
+ "Hashed relay params do not match existing relay hash for deposit"
818
+ );
819
+ }
820
+
821
+ // Return hash of unique instant relay and deposit event. This is stored in state and mapped to a deposit hash.
822
+ function _getInstantRelayHash(bytes32 depositHash, RelayData memory relayData) private pure returns (bytes32) {
823
+ // Only include parameters that affect the "correctness" of an instant relay. For example, the realized LP fee
824
+ // % directly affects how many tokens the instant relayer needs to send to the user, whereas the address of the
825
+ // instant relayer does not matter for determining whether an instant relay is "correct".
826
+ return keccak256(abi.encode(depositHash, relayData.realizedLpFeePct));
827
+ }
828
+
829
+ function _getAccumulatedFees() internal view returns (uint256) {
830
+ // UnallocatedLpFees := min(undistributedLpFees*lpFeeRatePerSecond*timeFromLastInteraction,undistributedLpFees)
831
+ // The min acts to pay out all fees in the case the equation returns more than the remaining a fees.
832
+ uint256 possibleUnpaidFees =
833
+ (undistributedLpFees * lpFeeRatePerSecond * (getCurrentTime() - lastLpFeeUpdate)) / (1e18);
834
+ return possibleUnpaidFees < undistributedLpFees ? possibleUnpaidFees : undistributedLpFees;
835
+ }
836
+
837
+ // Update internal fee counters by adding in any accumulated fees from the last time this logic was called.
838
+ function _updateAccumulatedLpFees() internal {
839
+ // Calculate the unallocatedAccumulatedFees from the last time the contract was called.
840
+ uint256 unallocatedAccumulatedFees = _getAccumulatedFees();
841
+
842
+ // Decrement the undistributedLpFees by the amount of accumulated fees.
843
+ undistributedLpFees = undistributedLpFees - unallocatedAccumulatedFees;
844
+
845
+ lastLpFeeUpdate = uint32(getCurrentTime());
846
+ }
847
+
848
+ // Allocate fees to the LPs by incrementing counters.
849
+ function _allocateLpFees(uint256 allocatedLpFees) internal {
850
+ // Add to the total undistributed LP fees and the utilized reserves. Adding it to the utilized reserves acts to
851
+ // track the fees while they are in transit.
852
+ undistributedLpFees += allocatedLpFees;
853
+ utilizedReserves += int256(allocatedLpFees);
854
+ }
855
+
856
+ function _getAmountFromPct(uint64 percent, uint256 amount) private pure returns (uint256) {
857
+ return (percent * amount) / 1e18;
858
+ }
859
+
860
+ function _getProposerBond(uint256 amount) private view returns (uint256) {
861
+ return _getAmountFromPct(proposerBondPct, amount);
862
+ }
863
+
864
+ function _getDepositHash(DepositData memory depositData) private view returns (bytes32) {
865
+ return keccak256(abi.encode(depositData, address(l1Token)));
866
+ }
867
+
868
+ // Proposes new price of True for relay event associated with `customAncillaryData` to optimistic oracle. If anyone
869
+ // disagrees with the relay parameters and whether they map to an L2 deposit, they can dispute with the oracle.
870
+ function _requestProposeDispute(
871
+ address proposer,
872
+ address disputer,
873
+ uint256 proposerBond,
874
+ uint256 finalFee,
875
+ bytes memory customAncillaryData
876
+ ) private returns (bool) {
877
+ uint256 totalBond = finalFee + proposerBond;
878
+ l1Token.safeApprove(address(optimisticOracle), totalBond);
879
+ try
880
+ optimisticOracle.requestAndProposePriceFor(
881
+ identifier,
882
+ uint32(getCurrentTime()),
883
+ customAncillaryData,
884
+ IERC20(l1Token),
885
+ // Set reward to 0, since we'll settle proposer reward payouts directly from this contract after a relay
886
+ // proposal has passed the challenge period.
887
+ 0,
888
+ // Set the Optimistic oracle proposer bond for the price request.
889
+ proposerBond,
890
+ // Set the Optimistic oracle liveness for the price request.
891
+ optimisticOracleLiveness,
892
+ proposer,
893
+ // Canonical value representing "True"; i.e. the proposed relay is valid.
894
+ int256(1e18)
895
+ )
896
+ returns (uint256 bondSpent) {
897
+ if (bondSpent < totalBond) {
898
+ // If the OO pulls less (due to a change in final fee), refund the proposer.
899
+ uint256 refund = totalBond - bondSpent;
900
+ l1Token.safeTransfer(proposer, refund);
901
+ l1Token.safeApprove(address(optimisticOracle), 0);
902
+ totalBond = bondSpent;
903
+ }
904
+ } catch {
905
+ // If there's an error in the OO, this means something has changed to make this request undisputable.
906
+ // To ensure the request does not go through by default, refund the proposer and return early, allowing
907
+ // the calling method to delete the request, but with no additional recourse by the OO.
908
+ l1Token.safeTransfer(proposer, totalBond);
909
+ l1Token.safeApprove(address(optimisticOracle), 0);
910
+
911
+ // Return early noting that the attempt at a proposal + dispute did not succeed.
912
+ return false;
913
+ }
914
+
915
+ SkinnyOptimisticOracleInterface.Request memory request =
916
+ SkinnyOptimisticOracleInterface.Request({
917
+ proposer: proposer,
918
+ disputer: address(0),
919
+ currency: IERC20(l1Token),
920
+ settled: false,
921
+ proposedPrice: int256(1e18),
922
+ resolvedPrice: 0,
923
+ expirationTime: getCurrentTime() + optimisticOracleLiveness,
924
+ reward: 0,
925
+ finalFee: totalBond - proposerBond,
926
+ bond: proposerBond,
927
+ customLiveness: uint256(optimisticOracleLiveness)
928
+ });
929
+
930
+ // Note: don't pull funds until here to avoid any transfers that aren't needed.
931
+ l1Token.safeTransferFrom(msg.sender, address(this), totalBond);
932
+ l1Token.safeApprove(address(optimisticOracle), totalBond);
933
+ // Dispute the request that we just sent.
934
+ optimisticOracle.disputePriceFor(
935
+ identifier,
936
+ uint32(getCurrentTime()),
937
+ customAncillaryData,
938
+ request,
939
+ disputer,
940
+ address(this)
941
+ );
942
+
943
+ // Return true to denote that the proposal + dispute calls succeeded.
944
+ return true;
945
+ }
946
+
947
+ // Unwraps ETH and does a transfer to a recipient address. If the recipient is a smart contract then sends WETH.
948
+ function _unwrapWETHTo(address payable to, uint256 amount) internal {
949
+ if (address(to).isContract()) {
950
+ l1Token.safeTransfer(to, amount);
951
+ } else {
952
+ WETH9Like(address(l1Token)).withdraw(amount);
953
+ to.transfer(amount);
954
+ }
955
+ }
956
+
957
+ // Added to enable the BridgePool to receive ETH. used when unwrapping Weth.
958
+ receive() external payable {}
959
+ }
960
+
961
+ /**
962
+ * @notice This is the BridgePool contract that should be deployed on live networks. It is exactly the same as the
963
+ * regular BridgePool contract, but it overrides getCurrentTime to make the call a simply return block.timestamp with
964
+ * no branching or storage queries. This is done to save gas.
965
+ */
966
+ contract BridgePoolProd is BridgePool {
967
+ constructor(
968
+ string memory _lpTokenName,
969
+ string memory _lpTokenSymbol,
970
+ address _bridgeAdmin,
971
+ address _l1Token,
972
+ uint64 _lpFeeRatePerSecond,
973
+ bool _isWethPool,
974
+ address _timer
975
+ ) BridgePool(_lpTokenName, _lpTokenSymbol, _bridgeAdmin, _l1Token, _lpFeeRatePerSecond, _isWethPool, _timer) {}
976
+
977
+ function getCurrentTime() public view virtual override returns (uint256) {
978
+ return block.timestamp;
979
+ }
980
+ }