@coti-io/coti-contracts 1.1.0 → 1.3.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 (433) hide show
  1. package/.github/workflows/npm-publish.yml +19 -15
  2. package/README.md +3 -1
  3. package/contracts/disperse/coinByRatio/FixedRatioCoinDisperser.sol +452 -0
  4. package/contracts/disperse/coinByRatio/FixedRatioCoinDisperserLeftoverS1.sol +490 -0
  5. package/contracts/disperse/coinByRatio/FixedRatioCoinDisperserUnlimitedWindow.sol +432 -0
  6. package/contracts/disperse/disperseToken/MintDisperser.sol +120 -0
  7. package/contracts/disperse/disperseToken/TokenDisperser.sol +139 -0
  8. package/contracts/messaging/PrivateMessaging.sol +456 -0
  9. package/contracts/mocks/messaging/PrivateMessagingHarness.sol +54 -0
  10. package/contracts/mocks/oracle/CotiPriceConsumerMock.sol +31 -0
  11. package/contracts/mocks/token/ERC20DecimalsMock.sol +21 -0
  12. package/contracts/mocks/token/ERC20Mock.sol +19 -0
  13. package/contracts/mocks/token/PrivateERC20/EncryptedTokenReceiverMock.sol +18 -0
  14. package/contracts/mocks/token/PrivateERC20/PrivacyBridgeERC20Mock.sol +18 -0
  15. package/contracts/mocks/token/PrivateERC20/PrivateERC20AuditorSupplyMock.sol +44 -0
  16. package/contracts/mocks/token/PrivateERC20/PrivateERC20CappedMock.sol +23 -0
  17. package/contracts/mocks/token/PrivateERC20/PrivateERC20GtCallerMock.sol +29 -0
  18. package/contracts/mocks/token/PrivateERC20/PrivateERC20Mock.sol +9 -4
  19. package/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol +39 -0
  20. package/contracts/mocks/token/PrivateERC20/PublicReentrantTokenReceiverMock.sol +29 -0
  21. package/contracts/mocks/token/PrivateERC20/PublicTokenReceiverBoolMock.sol +18 -0
  22. package/contracts/mocks/token/PrivateERC20/PublicTokenReceiverMock.sol +12 -0
  23. package/contracts/mocks/utils/mpc/Arithmetic128TestsContract.sol +123 -0
  24. package/contracts/mocks/utils/mpc/Arithmetic256TestsContract.sol +122 -0
  25. package/contracts/mocks/utils/mpc/Bitwise128TestsContract.sol +65 -0
  26. package/contracts/mocks/utils/mpc/Bitwise256TestsContract.sol +65 -0
  27. package/contracts/mocks/utils/mpc/CheckedArithmetic128WithOverflowBitTestsContract.sol +64 -0
  28. package/contracts/mocks/utils/mpc/CheckedArithmetic256WithOverflowBitTestsContract.sol +64 -0
  29. package/contracts/mocks/utils/mpc/Comparison128TestsContract.sol +98 -0
  30. package/contracts/mocks/utils/mpc/Comparison256TestsContract.sol +98 -0
  31. package/contracts/mocks/utils/mpc/MinMax128TestsContract.sol +44 -0
  32. package/contracts/mocks/utils/mpc/MinMax256TestsContract.sol +44 -0
  33. package/contracts/mocks/utils/mpc/MinimalImplementation.sol +55 -0
  34. package/contracts/mocks/utils/mpc/MinimalProxy.sol +27 -0
  35. package/contracts/mocks/utils/mpc/MpcOperations128TestContract.sol +267 -0
  36. package/contracts/mocks/utils/mpc/MpcOperationsTestContract.sol +334 -0
  37. package/contracts/mocks/utils/mpc/Mux128TestsContract.sol +24 -0
  38. package/contracts/mocks/utils/mpc/Mux256TestsContract.sol +24 -0
  39. package/contracts/mocks/utils/mpc/OnBoard128TestsContract.sol +93 -0
  40. package/contracts/mocks/utils/mpc/OnBoard256TestsContract.sol +116 -0
  41. package/contracts/mocks/utils/mpc/PrivacyImplementationV1.sol +157 -0
  42. package/contracts/mocks/utils/mpc/PrivacyImplementationV2.sol +133 -0
  43. package/contracts/mocks/utils/mpc/PrivacyProxy.sol +137 -0
  44. package/contracts/mocks/utils/mpc/Random128TestsContract.sol +32 -0
  45. package/contracts/mocks/utils/mpc/Random256TestsContract.sol +32 -0
  46. package/contracts/mocks/utils/mpc/Shift128TestsContract.sol +36 -0
  47. package/contracts/mocks/utils/mpc/Shift256TestsContract.sol +36 -0
  48. package/contracts/mocks/utils/mpc/Transfer128TestsContract.sol +29 -0
  49. package/contracts/mocks/utils/mpc/Transfer256TestsContract.sol +29 -0
  50. package/contracts/mocks/utils/mpc/TransferWithAllowance128TestsContract.sol +32 -0
  51. package/contracts/mocks/utils/mpc/TransferWithAllowance256TestsContract.sol +32 -0
  52. package/contracts/mocks/utils/mpc/ValidateCiphertext128TestsContract.sol +59 -0
  53. package/contracts/mocks/utils/mpc/ValidateCiphertext256TestsContract.sol +63 -0
  54. package/contracts/mocks/utils/mpc/ValidateCiphertextTestsContract.sol +99 -0
  55. package/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock.sol +7 -6
  56. package/contracts/node/CotiNodeRewards.sol +199 -0
  57. package/contracts/node/SoulboundNodeNFT.sol +519 -0
  58. package/contracts/oracle/CotiPriceConsumer.sol +103 -0
  59. package/contracts/oracle/ICotiPriceConsumer.sol +15 -0
  60. package/contracts/oracle/IStdReference.sol +26 -0
  61. package/contracts/privacyBridge/PrivacyBridge.sol +600 -0
  62. package/contracts/privacyBridge/PrivacyBridgeCotiNative.sol +316 -0
  63. package/contracts/privacyBridge/PrivacyBridgeERC20.sol +333 -0
  64. package/contracts/privacyBridge/PrivacyBridgeUSDCe.sol +22 -0
  65. package/contracts/privacyBridge/PrivacyBridgeUSDT.sol +23 -0
  66. package/contracts/privacyBridge/PrivacyBridgeWADA.sol +23 -0
  67. package/contracts/privacyBridge/PrivacyBridgeWBTC.sol +23 -0
  68. package/contracts/privacyBridge/PrivacyBridgeWETH.sol +23 -0
  69. package/contracts/privacyBridge/PrivacyBridgegCoti.sol +23 -0
  70. package/contracts/token/PrivateERC20/IPrivateERC20.sol +273 -40
  71. package/contracts/token/PrivateERC20/ITokenReceiver.sol +17 -0
  72. package/contracts/token/PrivateERC20/ITokenReceiverEncrypted.sol +20 -0
  73. package/contracts/token/PrivateERC20/PrivateERC20.sol +861 -152
  74. package/contracts/token/PrivateERC20/tokens/PrivateBridgedUSDC.sol +17 -0
  75. package/contracts/token/PrivateERC20/tokens/PrivateCOTI.sol +13 -0
  76. package/contracts/token/PrivateERC20/tokens/PrivateCOTITreasuryGovernanceToken.sol +17 -0
  77. package/contracts/token/PrivateERC20/tokens/PrivateTetherUSD.sol +17 -0
  78. package/contracts/token/PrivateERC20/tokens/PrivateWrappedADA.sol +17 -0
  79. package/contracts/token/PrivateERC20/tokens/PrivateWrappedBTC.sol +17 -0
  80. package/contracts/token/PrivateERC20/tokens/PrivateWrappedEther.sol +13 -0
  81. package/contracts/utils/mpc/MpcCore.sol +10780 -4962
  82. package/contracts/utils/mpc/MpcInterface.sol +7 -2
  83. package/hardhat/gasPriceBump.ts +60 -0
  84. package/hardhat.config.ts +63 -12
  85. package/package.json +22 -4
  86. package/scripts/add-bridge-operators.cjs +87 -0
  87. package/scripts/deploy-coti-price-consumer-mainnet.cjs +49 -0
  88. package/scripts/deployCotiNodeRewards.ts +51 -0
  89. package/scripts/deploySoulboundNodeNFT.ts +57 -0
  90. package/scripts/redeploy-private-and-bridges.cjs +201 -0
  91. package/scripts/set-bridge-limits-mainnet.cjs +177 -0
  92. package/scripts/verify-mainnet-private-bridges.cjs +289 -0
  93. package/sonar-project.properties +11 -0
  94. package/test/messaging/PrivateMessaging.test.ts +158 -0
  95. package/test/privacyBridge/UnifiedPrivacyBridges.test.cjs +1663 -0
  96. package/test/token/PrivateERC20/PrivacyBridge.fees.test.ts +250 -0
  97. package/test/token/PrivateERC20/PrivateERC20.test.ts +1109 -268
  98. package/test/utils/mpc/Bitwise128.test.ts +92 -0
  99. package/test/utils/mpc/Bitwise256.test.ts +101 -0
  100. package/test/utils/mpc/BuildInputText128.test.ts +398 -0
  101. package/test/utils/mpc/CheckedArithmetic128.test.ts +45 -0
  102. package/test/utils/mpc/CheckedArithmetic256.test.ts +45 -0
  103. package/test/utils/mpc/Comparison128.test.ts +48 -0
  104. package/test/utils/mpc/Comparison256.test.ts +48 -0
  105. package/test/utils/mpc/InvalidCiphertext.test.ts +179 -0
  106. package/test/utils/mpc/InvalidCiphertext128.test.ts +179 -0
  107. package/test/utils/mpc/InvalidCiphertext256.test.ts +201 -0
  108. package/test/utils/mpc/InvalidTransfer128.test.ts +166 -0
  109. package/test/utils/mpc/InvalidTransfer256.test.ts +158 -0
  110. package/test/utils/mpc/MinMax128.test.ts +44 -0
  111. package/test/utils/mpc/MinMax256.test.ts +44 -0
  112. package/test/utils/mpc/MinimalProxyDemo.test.ts +280 -0
  113. package/test/utils/mpc/MpcOperations.test.ts +589 -0
  114. package/test/utils/mpc/MpcOperations128.test.ts +632 -0
  115. package/test/utils/mpc/Mux128.test.ts +41 -0
  116. package/test/utils/mpc/Mux256.test.ts +41 -0
  117. package/test/utils/mpc/NegativeCases.test.ts +478 -0
  118. package/test/utils/mpc/NegativeCases128.test.ts +237 -0
  119. package/test/utils/mpc/NegativeCases256.test.ts +236 -0
  120. package/test/utils/mpc/OnBoard128.test.ts +90 -0
  121. package/test/utils/mpc/OnBoard256.test.ts +114 -0
  122. package/test/utils/mpc/Precompile128.test.ts +51 -0
  123. package/test/utils/mpc/Precompile256.test.ts +115 -0
  124. package/test/utils/mpc/ProxyValidation.test.ts +199 -0
  125. package/test/utils/mpc/Random128.test.ts +47 -0
  126. package/test/utils/mpc/Random256.test.ts +47 -0
  127. package/test/utils/mpc/Shift128.test.ts +41 -0
  128. package/test/utils/mpc/Shift256.test.ts +41 -0
  129. package/test/utils/mpc/Transfer128.test.ts +46 -0
  130. package/test/utils/mpc/Transfer256.test.ts +46 -0
  131. package/test/utils/mpc/TransferWithAllowance128.test.ts +48 -0
  132. package/test/utils/mpc/TransferWithAllowance256.test.ts +48 -0
  133. package/test/utils/mpc/UpgradeablePrivacyProxy.test.ts +307 -0
  134. package/test/utils/mpc/ValidateCiphertext.test.ts +221 -0
  135. package/test/utils/mpc/ValidateCiphertext256.test.ts +161 -0
  136. package/test/utils/mpc/ValidateCiphertext256Decryption.test.ts +383 -0
  137. package/test/utils/mpc/WalletEncryptionFailures.test.ts +494 -0
  138. package/test/utils/privateErc20Helpers.ts +97 -0
  139. package/typechain-types/@openzeppelin/contracts/access/AccessControl.ts +324 -0
  140. package/typechain-types/@openzeppelin/contracts/access/AccessControlEnumerable.ts +361 -0
  141. package/typechain-types/@openzeppelin/contracts/access/IAccessControl.ts +292 -0
  142. package/typechain-types/@openzeppelin/contracts/access/IAccessControlEnumerable.ts +329 -0
  143. package/typechain-types/@openzeppelin/contracts/access/Ownable.ts +153 -0
  144. package/typechain-types/@openzeppelin/contracts/access/index.ts +8 -0
  145. package/typechain-types/@openzeppelin/contracts/index.ts +4 -0
  146. package/typechain-types/@openzeppelin/contracts/security/Pausable.ts +150 -0
  147. package/typechain-types/@openzeppelin/contracts/security/index.ts +4 -0
  148. package/typechain-types/@openzeppelin/contracts/token/ERC20/ERC20.ts +330 -0
  149. package/typechain-types/@openzeppelin/contracts/token/ERC20/IERC20.ts +262 -0
  150. package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.ts +286 -0
  151. package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.ts +143 -0
  152. package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/index.ts +5 -0
  153. package/typechain-types/@openzeppelin/contracts/token/ERC20/index.ts +7 -0
  154. package/typechain-types/@openzeppelin/contracts/token/ERC721/ERC721.ts +420 -0
  155. package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.ts +420 -0
  156. package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/index.ts +4 -0
  157. package/typechain-types/@openzeppelin/contracts/token/ERC721/index.ts +3 -0
  158. package/typechain-types/@openzeppelin/contracts/token/index.ts +2 -0
  159. package/typechain-types/contracts/disperse/coinByRatio/FixedRatioCoinDisperser.ts +679 -0
  160. package/typechain-types/contracts/disperse/coinByRatio/FixedRatioCoinDisperserLeftoverS1.ts +735 -0
  161. package/typechain-types/contracts/disperse/coinByRatio/FixedRatioCoinDisperserUnlimitedWindow.ts +734 -0
  162. package/typechain-types/contracts/disperse/coinByRatio/index.ts +6 -0
  163. package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/IMintableERC20.ts +97 -0
  164. package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/IOwnable.ts +95 -0
  165. package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/MintDisperser.ts +228 -0
  166. package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/index.ts +6 -0
  167. package/typechain-types/contracts/disperse/disperseToken/TokenDisperser.ts +191 -0
  168. package/typechain-types/contracts/disperse/disperseToken/index.ts +6 -0
  169. package/typechain-types/contracts/disperse/index.ts +7 -0
  170. package/typechain-types/contracts/index.ts +10 -0
  171. package/typechain-types/contracts/messaging/PrivateMessaging.ts +871 -0
  172. package/typechain-types/contracts/messaging/index.ts +4 -0
  173. package/typechain-types/contracts/mocks/index.ts +4 -0
  174. package/typechain-types/contracts/mocks/messaging/PrivateMessagingHarness.ts +951 -0
  175. package/typechain-types/contracts/mocks/messaging/index.ts +4 -0
  176. package/typechain-types/contracts/mocks/oracle/CotiPriceConsumerMock.ts +163 -0
  177. package/typechain-types/contracts/mocks/oracle/index.ts +4 -0
  178. package/typechain-types/contracts/mocks/token/ERC20DecimalsMock.ts +349 -0
  179. package/typechain-types/contracts/mocks/token/ERC20Mock.ts +368 -0
  180. package/typechain-types/contracts/mocks/token/PrivateERC20/EncryptedTokenReceiverMock.ts +108 -0
  181. package/typechain-types/contracts/mocks/token/PrivateERC20/PrivacyBridgeERC20Mock.ts +1892 -0
  182. package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20AuditorSupplyMock.ts +1296 -0
  183. package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20CappedMock.ts +1270 -0
  184. package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20GtCallerMock.ts +166 -0
  185. package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20Mock.ts +827 -78
  186. package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/IPrivateERC20TransferAndCallEncrypted.ts +102 -0
  187. package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/PrivateERC20ReentrantReceiverMock.ts +154 -0
  188. package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/index.ts +5 -0
  189. package/typechain-types/contracts/mocks/token/PrivateERC20/PublicReentrantTokenReceiverMock.ts +155 -0
  190. package/typechain-types/contracts/mocks/token/PrivateERC20/PublicTokenReceiverBoolMock.ts +107 -0
  191. package/typechain-types/contracts/mocks/token/PrivateERC20/PublicTokenReceiverMock.ts +100 -0
  192. package/typechain-types/contracts/mocks/token/PrivateERC20/index.ts +10 -0
  193. package/typechain-types/contracts/mocks/token/index.ts +2 -0
  194. package/typechain-types/contracts/mocks/utils/mpc/{Arithmetic128BitTestsContract.ts → Arithmetic128TestsContract.ts} +96 -126
  195. package/typechain-types/contracts/mocks/utils/mpc/{Arithmetic256BitTestsContract.ts → Arithmetic256TestsContract.ts} +97 -133
  196. package/typechain-types/contracts/mocks/utils/mpc/{Bitwise128BitTestsContract.ts → Bitwise128TestsContract.ts} +52 -59
  197. package/typechain-types/contracts/mocks/utils/mpc/{Bitwise256BitTestsContract.ts → Bitwise256TestsContract.ts} +52 -59
  198. package/typechain-types/contracts/mocks/utils/mpc/CheckedArithmetic128WithOverflowBitTestsContract.ts +206 -0
  199. package/typechain-types/contracts/mocks/utils/mpc/CheckedArithmetic256WithOverflowBitTestsContract.ts +206 -0
  200. package/typechain-types/contracts/mocks/utils/mpc/{Comparison128BitTestsContract.ts → Comparison128TestsContract.ts} +115 -97
  201. package/typechain-types/contracts/mocks/utils/mpc/{Comparison256BitTestsContract.ts → Comparison256TestsContract.ts} +115 -97
  202. package/typechain-types/contracts/mocks/utils/mpc/MinMax128TestsContract.ts +142 -0
  203. package/typechain-types/contracts/mocks/utils/mpc/MinMax256TestsContract.ts +142 -0
  204. package/typechain-types/contracts/mocks/utils/mpc/MinimalImplementation.ts +259 -0
  205. package/typechain-types/contracts/mocks/utils/mpc/MinimalProxy.ts +90 -0
  206. package/typechain-types/contracts/mocks/utils/mpc/MpcOperations128TestContract.ts +388 -0
  207. package/typechain-types/contracts/mocks/utils/mpc/MpcOperationsTestContract.ts +455 -0
  208. package/typechain-types/contracts/mocks/utils/mpc/Mux128TestsContract.ts +109 -0
  209. package/typechain-types/contracts/mocks/utils/mpc/Mux256TestsContract.ts +109 -0
  210. package/typechain-types/contracts/mocks/utils/mpc/OnBoard128TestsContract.ts +166 -0
  211. package/typechain-types/contracts/mocks/utils/mpc/OnBoard256TestsContract.ts +194 -0
  212. package/typechain-types/contracts/mocks/utils/mpc/PrivacyImplementationV1.ts +385 -0
  213. package/typechain-types/contracts/mocks/utils/mpc/PrivacyImplementationV2.ts +441 -0
  214. package/typechain-types/contracts/mocks/utils/mpc/PrivacyProxy.ts +201 -0
  215. package/typechain-types/contracts/mocks/utils/mpc/Random128TestsContract.ts +131 -0
  216. package/typechain-types/contracts/mocks/utils/mpc/Random256TestsContract.ts +131 -0
  217. package/typechain-types/contracts/mocks/utils/mpc/Shift128TestsContract.ts +142 -0
  218. package/typechain-types/contracts/mocks/utils/mpc/Shift256TestsContract.ts +142 -0
  219. package/typechain-types/contracts/mocks/utils/mpc/Transfer128TestsContract.ts +109 -0
  220. package/typechain-types/contracts/mocks/utils/mpc/Transfer256TestsContract.ts +109 -0
  221. package/typechain-types/contracts/mocks/utils/mpc/TransferWithAllowance128TestsContract.ts +128 -0
  222. package/typechain-types/contracts/mocks/utils/mpc/TransferWithAllowance256TestsContract.ts +128 -0
  223. package/typechain-types/contracts/mocks/utils/mpc/ValidateCiphertext128TestsContract.ts +198 -0
  224. package/typechain-types/contracts/mocks/utils/mpc/ValidateCiphertext256TestsContract.ts +182 -0
  225. package/typechain-types/contracts/mocks/utils/mpc/ValidateCiphertextTestsContract.ts +257 -0
  226. package/typechain-types/contracts/mocks/utils/mpc/index.ts +32 -8
  227. package/typechain-types/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock.ts +6 -6
  228. package/typechain-types/contracts/node/CotiNodeRewards.ts +566 -0
  229. package/typechain-types/contracts/node/SoulboundNodeNFT.sol/IERC5192.ts +123 -0
  230. package/typechain-types/contracts/node/SoulboundNodeNFT.sol/SoulboundNodeNFT.ts +975 -0
  231. package/typechain-types/contracts/node/SoulboundNodeNFT.sol/index.ts +5 -0
  232. package/typechain-types/contracts/node/index.ts +6 -0
  233. package/typechain-types/contracts/oracle/CotiPriceConsumer.ts +256 -0
  234. package/typechain-types/contracts/oracle/ICotiPriceConsumer.ts +119 -0
  235. package/typechain-types/contracts/oracle/IStdReference.ts +136 -0
  236. package/typechain-types/contracts/oracle/index.ts +6 -0
  237. package/typechain-types/contracts/privacyBridge/PrivacyBridge.ts +1628 -0
  238. package/typechain-types/contracts/privacyBridge/PrivacyBridgeCotiNative.ts +1870 -0
  239. package/typechain-types/contracts/privacyBridge/PrivacyBridgeERC20.sol/IHasDecimals.ts +84 -0
  240. package/typechain-types/contracts/privacyBridge/PrivacyBridgeERC20.sol/PrivacyBridgeERC20.ts +1892 -0
  241. package/typechain-types/contracts/privacyBridge/PrivacyBridgeERC20.sol/index.ts +5 -0
  242. package/typechain-types/contracts/privacyBridge/PrivacyBridgeUSDCe.ts +1892 -0
  243. package/typechain-types/contracts/privacyBridge/PrivacyBridgeUSDT.ts +1892 -0
  244. package/typechain-types/contracts/privacyBridge/PrivacyBridgeWADA.ts +1892 -0
  245. package/typechain-types/contracts/privacyBridge/PrivacyBridgeWBTC.ts +1892 -0
  246. package/typechain-types/contracts/privacyBridge/PrivacyBridgeWETH.ts +1892 -0
  247. package/typechain-types/contracts/privacyBridge/PrivacyBridgegCoti.ts +1892 -0
  248. package/typechain-types/contracts/privacyBridge/index.ts +13 -0
  249. package/typechain-types/contracts/token/PrivateERC20/IPrivateERC20.ts +507 -70
  250. package/typechain-types/contracts/token/PrivateERC20/ITokenReceiver.ts +100 -0
  251. package/typechain-types/contracts/token/PrivateERC20/ITokenReceiverEncrypted.ts +99 -0
  252. package/typechain-types/contracts/token/PrivateERC20/PrivateERC20.ts +833 -68
  253. package/typechain-types/contracts/token/PrivateERC20/index.ts +4 -0
  254. package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateBridgedUSDC.ts +1270 -0
  255. package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateCOTI.ts +1270 -0
  256. package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateCOTITreasuryGovernanceToken.ts +1270 -0
  257. package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateTetherUSD.ts +1270 -0
  258. package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateWrappedADA.ts +1270 -0
  259. package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateWrappedBTC.ts +1270 -0
  260. package/typechain-types/contracts/token/PrivateERC20/tokens/PrivateWrappedEther.ts +1270 -0
  261. package/typechain-types/contracts/token/PrivateERC20/tokens/index.ts +10 -0
  262. package/typechain-types/contracts/utils/mpc/MpcInterface.sol/ExtendedOperations.ts +111 -10
  263. package/typechain-types/factories/@openzeppelin/contracts/access/AccessControlEnumerable__factory.ts +276 -0
  264. package/typechain-types/factories/@openzeppelin/contracts/access/AccessControl__factory.ts +229 -0
  265. package/typechain-types/factories/@openzeppelin/contracts/access/IAccessControlEnumerable__factory.ts +244 -0
  266. package/typechain-types/factories/@openzeppelin/contracts/access/IAccessControl__factory.ts +197 -0
  267. package/typechain-types/factories/@openzeppelin/contracts/access/Ownable__factory.ts +74 -0
  268. package/typechain-types/factories/@openzeppelin/contracts/access/index.ts +8 -0
  269. package/typechain-types/factories/@openzeppelin/contracts/index.ts +2 -0
  270. package/typechain-types/factories/@openzeppelin/contracts/security/Pausable__factory.ts +61 -0
  271. package/typechain-types/factories/@openzeppelin/contracts/security/index.ts +4 -0
  272. package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/ERC20__factory.ts +356 -0
  273. package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/IERC20__factory.ts +205 -0
  274. package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata__factory.ts +247 -0
  275. package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit__factory.ts +100 -0
  276. package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/index.ts +5 -0
  277. package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/index.ts +6 -0
  278. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/ERC721__factory.ts +416 -0
  279. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata__factory.ts +355 -0
  280. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/index.ts +4 -0
  281. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/index.ts +2 -0
  282. package/typechain-types/factories/@openzeppelin/contracts/token/index.ts +1 -0
  283. package/typechain-types/factories/contracts/disperse/coinByRatio/FixedRatioCoinDisperserLeftoverS1__factory.ts +791 -0
  284. package/typechain-types/factories/contracts/disperse/coinByRatio/FixedRatioCoinDisperserUnlimitedWindow__factory.ts +711 -0
  285. package/typechain-types/factories/contracts/disperse/coinByRatio/FixedRatioCoinDisperser__factory.ts +759 -0
  286. package/typechain-types/factories/contracts/disperse/coinByRatio/index.ts +6 -0
  287. package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/IMintableERC20__factory.ts +43 -0
  288. package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/IOwnable__factory.ts +35 -0
  289. package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/MintDisperser__factory.ts +203 -0
  290. package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/index.ts +6 -0
  291. package/typechain-types/factories/contracts/disperse/disperseToken/TokenDisperser__factory.ts +198 -0
  292. package/typechain-types/factories/contracts/disperse/disperseToken/index.ts +5 -0
  293. package/typechain-types/factories/contracts/disperse/index.ts +5 -0
  294. package/typechain-types/factories/contracts/index.ts +5 -0
  295. package/typechain-types/factories/contracts/messaging/PrivateMessaging__factory.ts +1035 -0
  296. package/typechain-types/factories/contracts/messaging/index.ts +4 -0
  297. package/typechain-types/factories/contracts/mocks/access/DataPrivacyFramework/DataPrivacyFrameworkMock__factory.ts +1 -1
  298. package/typechain-types/factories/contracts/mocks/index.ts +2 -0
  299. package/typechain-types/factories/contracts/mocks/messaging/PrivateMessagingHarness__factory.ts +1161 -0
  300. package/typechain-types/factories/contracts/mocks/messaging/index.ts +4 -0
  301. package/typechain-types/factories/contracts/mocks/oracle/CotiPriceConsumerMock__factory.ts +159 -0
  302. package/typechain-types/factories/contracts/mocks/oracle/index.ts +4 -0
  303. package/typechain-types/factories/contracts/mocks/token/ERC20DecimalsMock__factory.ts +394 -0
  304. package/typechain-types/factories/contracts/mocks/token/ERC20Mock__factory.ts +392 -0
  305. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/EncryptedTokenReceiverMock__factory.ts +125 -0
  306. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivacyBridgeERC20Mock__factory.ts +1797 -0
  307. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20AuditorSupplyMock__factory.ts +1514 -0
  308. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20CappedMock__factory.ts +1466 -0
  309. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20GtCallerMock__factory.ts +165 -0
  310. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20Mock__factory.ts +975 -127
  311. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/IPrivateERC20TransferAndCallEncrypted__factory.ts +54 -0
  312. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/PrivateERC20ReentrantReceiverMock__factory.ts +159 -0
  313. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol/index.ts +5 -0
  314. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PublicReentrantTokenReceiverMock__factory.ts +164 -0
  315. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PublicTokenReceiverBoolMock__factory.ts +130 -0
  316. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PublicTokenReceiverMock__factory.ts +102 -0
  317. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/index.ts +9 -0
  318. package/typechain-types/factories/contracts/mocks/token/PrivateERC721/PrivateERC721URIStorageMock__factory.ts +1 -1
  319. package/typechain-types/factories/contracts/mocks/token/index.ts +2 -0
  320. package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic128TestsContract__factory.ts +330 -0
  321. package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic256TestsContract__factory.ts +330 -0
  322. package/typechain-types/factories/contracts/mocks/utils/mpc/ArithmeticTestsContract__factory.ts +1 -1
  323. package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise128TestsContract__factory.ts +184 -0
  324. package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise256TestsContract__factory.ts +184 -0
  325. package/typechain-types/factories/contracts/mocks/utils/mpc/BitwiseTestsContract__factory.ts +1 -1
  326. package/typechain-types/factories/contracts/mocks/utils/mpc/CheckedArithmetic128WithOverflowBitTestsContract__factory.ts +203 -0
  327. package/typechain-types/factories/contracts/mocks/utils/mpc/CheckedArithmetic256WithOverflowBitTestsContract__factory.ts +203 -0
  328. package/typechain-types/factories/contracts/mocks/utils/mpc/CheckedArithmeticWIthOverflowBitTestsContract.sol/CheckedArithmeticWithOverflowBitTestsContract__factory.ts +1 -1
  329. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison128TestsContract__factory.ts +295 -0
  330. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison1TestsContract__factory.ts +1 -1
  331. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison256TestsContract__factory.ts +295 -0
  332. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison2TestsContract__factory.ts +1 -1
  333. package/typechain-types/factories/contracts/mocks/utils/mpc/MinMax128TestsContract__factory.ts +147 -0
  334. package/typechain-types/factories/contracts/mocks/utils/mpc/MinMax256TestsContract__factory.ts +147 -0
  335. package/typechain-types/factories/contracts/mocks/utils/mpc/MinMaxTestsContract__factory.ts +1 -1
  336. package/typechain-types/factories/contracts/mocks/utils/mpc/MinimalImplementation__factory.ts +263 -0
  337. package/typechain-types/factories/contracts/mocks/utils/mpc/MinimalProxy__factory.ts +104 -0
  338. package/typechain-types/factories/contracts/mocks/utils/mpc/Miscellaneous1TestsContract__factory.ts +1 -1
  339. package/typechain-types/factories/contracts/mocks/utils/mpc/MiscellaneousTestsContract__factory.ts +1 -1
  340. package/typechain-types/factories/contracts/mocks/utils/mpc/MpcOperations128TestContract__factory.ts +723 -0
  341. package/typechain-types/factories/contracts/mocks/utils/mpc/MpcOperationsTestContract__factory.ts +1410 -0
  342. package/typechain-types/factories/contracts/mocks/utils/mpc/Mux128TestsContract__factory.ts +115 -0
  343. package/typechain-types/factories/contracts/mocks/utils/mpc/Mux256TestsContract__factory.ts +115 -0
  344. package/typechain-types/factories/contracts/mocks/utils/mpc/OffboardToUserKeyTestContract__factory.ts +1 -1
  345. package/typechain-types/factories/contracts/mocks/utils/mpc/OnBoard128TestsContract__factory.ts +175 -0
  346. package/typechain-types/factories/contracts/mocks/utils/mpc/OnBoard256TestsContract__factory.ts +205 -0
  347. package/typechain-types/factories/contracts/mocks/utils/mpc/PrivacyImplementationV1__factory.ts +521 -0
  348. package/typechain-types/factories/contracts/mocks/utils/mpc/PrivacyImplementationV2__factory.ts +648 -0
  349. package/typechain-types/factories/contracts/mocks/utils/mpc/PrivacyProxy__factory.ts +179 -0
  350. package/typechain-types/factories/contracts/mocks/utils/mpc/Random128TestsContract__factory.ts +131 -0
  351. package/typechain-types/factories/contracts/mocks/utils/mpc/Random256TestsContract__factory.ts +131 -0
  352. package/typechain-types/factories/contracts/mocks/utils/mpc/Shift128TestsContract__factory.ts +147 -0
  353. package/typechain-types/factories/contracts/mocks/utils/mpc/Shift256TestsContract__factory.ts +147 -0
  354. package/typechain-types/factories/contracts/mocks/utils/mpc/ShiftTestsContract__factory.ts +1 -1
  355. package/typechain-types/factories/contracts/mocks/utils/mpc/StringTestsContract__factory.ts +1 -1
  356. package/typechain-types/factories/contracts/mocks/utils/mpc/Transfer128TestsContract__factory.ts +135 -0
  357. package/typechain-types/factories/contracts/mocks/utils/mpc/Transfer256TestsContract__factory.ts +135 -0
  358. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferScalarTestsContract__factory.ts +1 -1
  359. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferTestsContract__factory.ts +1 -1
  360. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance128TestsContract__factory.ts +154 -0
  361. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance256TestsContract__factory.ts +154 -0
  362. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_16TestsContract__factory.ts +1 -1
  363. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_32TestsContract__factory.ts +1 -1
  364. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_64TestsContract__factory.ts +1 -1
  365. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_8TestsContract__factory.ts +1 -1
  366. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowanceScalarTestsContract__factory.ts +1 -1
  367. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowanceTestsContract__factory.ts +1 -1
  368. package/typechain-types/factories/contracts/mocks/utils/mpc/ValidateCiphertext128TestsContract__factory.ts +190 -0
  369. package/typechain-types/factories/contracts/mocks/utils/mpc/ValidateCiphertext256TestsContract__factory.ts +210 -0
  370. package/typechain-types/factories/contracts/mocks/utils/mpc/ValidateCiphertextTestsContract__factory.ts +260 -0
  371. package/typechain-types/factories/contracts/mocks/utils/mpc/index.ts +32 -8
  372. package/typechain-types/factories/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock__factory.ts +10 -28
  373. package/typechain-types/factories/contracts/node/CotiNodeRewards__factory.ts +549 -0
  374. package/typechain-types/factories/contracts/node/SoulboundNodeNFT.sol/IERC5192__factory.ts +54 -0
  375. package/typechain-types/factories/contracts/node/SoulboundNodeNFT.sol/SoulboundNodeNFT__factory.ts +947 -0
  376. package/typechain-types/factories/contracts/node/SoulboundNodeNFT.sol/index.ts +5 -0
  377. package/typechain-types/factories/contracts/node/index.ts +5 -0
  378. package/typechain-types/factories/contracts/onboard/AccountOnboard__factory.ts +1 -1
  379. package/typechain-types/factories/contracts/oracle/CotiPriceConsumer__factory.ts +295 -0
  380. package/typechain-types/factories/contracts/oracle/ICotiPriceConsumer__factory.ts +73 -0
  381. package/typechain-types/factories/contracts/oracle/IStdReference__factory.ts +107 -0
  382. package/typechain-types/factories/contracts/oracle/index.ts +6 -0
  383. package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeCotiNative__factory.ts +1676 -0
  384. package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeERC20.sol/IHasDecimals__factory.ts +38 -0
  385. package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeERC20.sol/PrivacyBridgeERC20__factory.ts +1678 -0
  386. package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeERC20.sol/index.ts +5 -0
  387. package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeUSDCe__factory.ts +1782 -0
  388. package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeUSDT__factory.ts +1782 -0
  389. package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeWADA__factory.ts +1782 -0
  390. package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeWBTC__factory.ts +1782 -0
  391. package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgeWETH__factory.ts +1782 -0
  392. package/typechain-types/factories/contracts/privacyBridge/PrivacyBridge__factory.ts +1367 -0
  393. package/typechain-types/factories/contracts/privacyBridge/PrivacyBridgegCoti__factory.ts +1782 -0
  394. package/typechain-types/factories/contracts/privacyBridge/index.ts +12 -0
  395. package/typechain-types/factories/contracts/token/PrivateERC20/IPrivateERC20__factory.ts +639 -61
  396. package/typechain-types/factories/contracts/token/PrivateERC20/ITokenReceiverEncrypted__factory.ts +53 -0
  397. package/typechain-types/factories/contracts/token/PrivateERC20/ITokenReceiver__factory.ts +54 -0
  398. package/typechain-types/factories/contracts/token/PrivateERC20/PrivateERC20__factory.ts +986 -120
  399. package/typechain-types/factories/contracts/token/PrivateERC20/index.ts +3 -0
  400. package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateBridgedUSDC__factory.ts +1445 -0
  401. package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateCOTITreasuryGovernanceToken__factory.ts +1451 -0
  402. package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateCOTI__factory.ts +1442 -0
  403. package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateTetherUSD__factory.ts +1445 -0
  404. package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateWrappedADA__factory.ts +1445 -0
  405. package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateWrappedBTC__factory.ts +1445 -0
  406. package/typechain-types/factories/contracts/token/PrivateERC20/tokens/PrivateWrappedEther__factory.ts +1451 -0
  407. package/typechain-types/factories/contracts/token/PrivateERC20/tokens/index.ts +10 -0
  408. package/typechain-types/factories/contracts/utils/mpc/MpcCore__factory.ts +1 -1
  409. package/typechain-types/factories/contracts/utils/mpc/MpcInterface.sol/ExtendedOperations__factory.ts +126 -0
  410. package/typechain-types/hardhat.d.ts +1772 -278
  411. package/typechain-types/index.ts +182 -16
  412. package/contracts/mocks/utils/mpc/Arithmetic128BitTestsContract.sol +0 -260
  413. package/contracts/mocks/utils/mpc/Arithmetic256BitTestsContract.sol +0 -264
  414. package/contracts/mocks/utils/mpc/Bitwise128BitTestsContract.sol +0 -91
  415. package/contracts/mocks/utils/mpc/Bitwise256BitTestsContract.sol +0 -91
  416. package/contracts/mocks/utils/mpc/Comparison128BitTestsContract.sol +0 -158
  417. package/contracts/mocks/utils/mpc/Comparison256BitTestsContract.sol +0 -158
  418. package/contracts/mocks/utils/mpc/Miscellaneous128BitTestsContract.sol +0 -185
  419. package/contracts/mocks/utils/mpc/Miscellaneous256BitTestsContract.sol +0 -190
  420. package/contracts/mocks/utils/mpc/README.md +0 -486
  421. package/test/utils/mpc/Unsigned128BitIntegers.test.ts +0 -945
  422. package/test/utils/mpc/Unsigned256BitIntegers.test.ts +0 -1124
  423. package/test/utils/mpc/helpers.ts +0 -77
  424. package/typechain-types/contracts/mocks/utils/mpc/Miscellaneous128BitTestsContract.ts +0 -302
  425. package/typechain-types/contracts/mocks/utils/mpc/Miscellaneous256BitTestsContract.ts +0 -322
  426. package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic128BitTestsContract__factory.ts +0 -349
  427. package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic256BitTestsContract__factory.ts +0 -364
  428. package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise128BitTestsContract__factory.ts +0 -182
  429. package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise256BitTestsContract__factory.ts +0 -182
  430. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison128BitTestsContract__factory.ts +0 -255
  431. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison256BitTestsContract__factory.ts +0 -255
  432. package/typechain-types/factories/contracts/mocks/utils/mpc/Miscellaneous128BitTestsContract__factory.ts +0 -332
  433. package/typechain-types/factories/contracts/mocks/utils/mpc/Miscellaneous256BitTestsContract__factory.ts +0 -380
@@ -0,0 +1,600 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.19;
3
+
4
+ import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
5
+ import "@openzeppelin/contracts/security/Pausable.sol";
6
+ import "@openzeppelin/contracts/access/Ownable.sol";
7
+ import "@openzeppelin/contracts/access/AccessControlEnumerable.sol";
8
+ import "../oracle/ICotiPriceConsumer.sol";
9
+
10
+ /**
11
+ * @title PrivacyBridge
12
+ * @notice Base contract for Privacy Bridge contracts containing common logic
13
+ * @dev Trust assumptions: (1) MPC precompile at expected address is correct and non-malicious.
14
+ * (2) Private token implementation is trusted and only authorized minters can mint.
15
+ * (3) Pause and rescue (governance-critical): The owner can {pause}. While paused, derived bridges expose
16
+ * owner-only rescue entry points ({PrivacyBridgeCotiNative.rescueNative}, {PrivacyBridgeERC20.rescueERC20})
17
+ * that send value to {rescueRecipient}. Those calls can transfer the contract's entire relevant balance,
18
+ * including liquidity that backs user obligations (full TVL migration). That is the intended emergency
19
+ * response after a bug or to retire a deployment; it is not enforced user-by-user on-chain. Treat
20
+ * owner key compromise after pause as catastrophic TVL loss to {rescueRecipient}. Mitigations are
21
+ * operational: multisig or timelock on ownership, strict {rescueRecipient} policy, monitoring of
22
+ * {Paused} and rescue events, and separation of duties where possible.
23
+ * (4) Oracle prices are trusted; {maxOracleAge} bounds staleness of `lastUpdated` (owner cannot set it to zero;
24
+ * use a large value only if a very lenient window is intended). Does not remove oracle trust.
25
+ * (5) {totalUserLiability} is bridge bookkeeping for transparency: it tracks net user obligations from mint/burn
26
+ * paths in this contract only. It helps depositors/observers reason about exposure; it is not a
27
+ * cryptographic proof of MPC/private-token balances and can diverge if the token layer misbehaves.
28
+ * **Docs / integrators:** Compare this counter to collateral still held by *this* contract (ERC20:
29
+ * {PrivacyBridgeERC20.token} balance; native: {address(this).balance}) for a liquidity snapshot. After
30
+ * {rescueERC20}/{rescueNative}, collateral may sit at {rescueRecipient} while this counter is unchanged—
31
+ * economic claims on outstanding private supply are not extinguished by rescue; do not treat the counter
32
+ * as “assets on hand” post-migration. Forced native (e.g. `selfdestruct`) increases balance but **never**
33
+ * mints private tokens and does **not** increase {totalUserLiability} (no user deposit path).
34
+ * (6) For COTI-operated deployments, residual trust in MPC/private-token behavior beyond (2) and (5), and in oracle
35
+ * *market* correctness beyond (4), is an accepted operational assumption; the on-chain mitigations above
36
+ * are the intended scope for those concerns in this module.
37
+ * (7) **Centralized control:** A single `Ownable` owner and any `OPERATOR_ROLE` grantees can configure pause,
38
+ * oracle rotation, deposit/withdraw limits, blacklist, and fee *parameters* (floors/caps/percentages) exposed
39
+ * in this module. **Fee and rescue destinations are fixed at deployment**—there are no setters for
40
+ * {feeRecipient} or {rescueRecipient}, so a compromised owner **cannot** redirect rescue or fee sweep
41
+ * addresses to an attacker (trade-off: a wrong address at deploy or a reverting recipient must be handled
42
+ * operationally / via migration). {transferOwnership} enumerates and revokes all role members, which can
43
+ * become gas-heavy with many operators; that cost is accepted. The contracts are not upgradeable via
44
+ * delegatecall within this package. Operational mitigations are off-chain: multisig or timelock on
45
+ * ownership, least-privilege operators, and monitoring.
46
+ * (8) **Oracle binding:** {_validateOracleTimestamps} requires exact equality to the user-supplied Band row
47
+ * timestamps so the fee quote cannot change between estimate and execution without a revert. With a
48
+ * typical ~30 minute feed cadence (plus {maxOracleAge} buffer), users have ample time to sign and submit
49
+ * the same row; relaxing this binding is intentionally rejected to avoid showing one price and settling
50
+ * at another.
51
+ */
52
+ abstract contract PrivacyBridge is ReentrancyGuard, Pausable, Ownable, AccessControlEnumerable {
53
+ bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
54
+
55
+ event OperatorAdded(address indexed account, address indexed by);
56
+ event OperatorRemoved(address indexed account, address indexed by);
57
+ event DepositEnabledUpdated(bool enabled, address indexed by);
58
+ event DynamicFeeUpdated(string feeType, uint256 fixedFee, uint256 percentageBps, uint256 maxFee);
59
+ event PriceOracleUpdated(address indexed oldOracle, address indexed newOracle);
60
+ event MaxOracleAgeUpdated(uint256 maxOracleAge, address indexed by);
61
+
62
+ /// @notice Maximum amount that can be deposited in a single transaction
63
+ uint256 public maxDepositAmount;
64
+
65
+ /// @notice Maximum amount that can be withdrawn in a single transaction
66
+ uint256 public maxWithdrawAmount;
67
+
68
+ /// @notice Minimum amount required for a deposit
69
+ uint256 public minDepositAmount;
70
+
71
+ /// @notice Minimum amount required for a withdrawal
72
+ uint256 public minWithdrawAmount;
73
+
74
+ /// @notice Booked native COTI fees not yet swept: both {PrivacyBridgeCotiNative} (deposit/withdraw fees)
75
+ /// and ERC20 bridges (per-operation dynamic native fee via {_collectDynamicNativeFee}) credit this counter.
76
+ /// Native bridge: {PrivacyBridgeCotiNative.withdrawFees}; ERC20 deployments: {withdrawCotiFees}.
77
+ uint256 public accumulatedCotiFees;
78
+
79
+ /// @notice On-chain aggregate of bridge-issued user obligations from deposit/withdraw mint and burn paths
80
+ /// (native: net private minted; native withdraw: private burned; ERC20: public received in / amount out).
81
+ /// Intended for transparency so depositors and tooling can read how much liability the bridge tracks
82
+ /// in its own accounting. This does not attest to MPC correctness or encrypted token balances.
83
+ /// @dev Same scope as contract-level @dev (5): updates only follow explicit mint/burn paths; unsolicited native
84
+ /// (e.g. `selfdestruct`) does **not** increase this value and does not mint private tokens. If the private
85
+ /// token or MPC layer misreports or mis-mints, this counter can diverge from economic reality. Do not
86
+ /// treat it as a solvency proof or substitute for off-chain audits of the private ledger. Emergency
87
+ /// {rescueERC20}/{rescueNative} moves collateral out but does **not** change this counter—obligations
88
+ /// implied by outstanding private supply may then exceed assets held here until migration elsewhere.
89
+ /// **Integrators:** compare to on-contract collateral (see contract @dev (5)).
90
+ uint256 public totalUserLiability;
91
+
92
+ /// @notice Fee divisor (1,000,000). Fee math uses {Math.mulDiv} (OpenZeppelin): integer division **rounds down**
93
+ /// (toward zero) at each step, so on-chain fees are at most a few wei **lower** than an idealized
94
+ /// floating-point quote—bias slightly favors users, not the fee recipient.
95
+ /// @dev Pathological `amount` × oracle rate products can still overflow `uint256` and revert—operators should
96
+ /// set deposit/withdraw limits accordingly.
97
+ uint256 public constant FEE_DIVISOR = 1000000;
98
+
99
+ /// @notice Maximum fee allowed (10% = 100,000 units)
100
+ uint256 public constant MAX_FEE_UNITS = 100000;
101
+
102
+ /// @notice Flag to enable/disable deposits
103
+ bool public isDepositEnabled = true;
104
+
105
+ // Privacy Bridge defines default Fees
106
+ // those fees can be overwritten using
107
+ // setDepositDynamicFee available for OPERATORS and ADMIN
108
+
109
+ /// @notice Deposit fee floor in COTI wei
110
+ uint256 public depositFixedFee = 10 ether;
111
+
112
+ /// @notice Deposit percentage (500/1,000,000 = 0.05%)
113
+ uint256 public depositPercentageBps = 500;
114
+
115
+ /// @notice Deposit fee cap in COTI wei
116
+ uint256 public depositMaxFee = 3000 ether;
117
+
118
+ /// @notice Withdraw fee floor in COTI wei
119
+ uint256 public withdrawFixedFee = 3 ether;
120
+
121
+ /// @notice Withdraw percentage (250/1,000,000 = 0.025%)
122
+ uint256 public withdrawPercentageBps = 250;
123
+
124
+ /// @notice Withdraw fee cap in COTI wei
125
+ uint256 public withdrawMaxFee = 1500 ether;
126
+
127
+ // --- END OF DEFAULT FEES
128
+
129
+ /// @notice CotiPriceConsumer contract address (non-zero at construction; owner may {setPriceOracle} to rotate)
130
+ address public priceOracle;
131
+
132
+ /// @notice Default max oracle age: nominal ~30 minute feed cadence plus a 5 minute buffer so slightly delayed
133
+ /// updates or inclusion lag do not spuriously revert with {OraclePriceStale}.
134
+ uint256 public constant DEFAULT_MAX_ORACLE_AGE = 30 minutes + 5 minutes;
135
+
136
+ /// @notice Maximum allowed `block.timestamp - oracle lastUpdated` (seconds). Initialized to {DEFAULT_MAX_ORACLE_AGE};
137
+ /// owner may increase the window (e.g. for long test runs) but {setMaxOracleAge} rejects zero.
138
+ uint256 public maxOracleAge;
139
+
140
+ /// @notice Address where collected fees are sent (fixed at deploy; no setter—see contract @dev (7))
141
+ address public feeRecipient;
142
+
143
+ /// @notice Address where rescued funds are sent (fixed at deploy; no setter—see contract @dev (7))
144
+ address public rescueRecipient;
145
+
146
+ error AmountZero();
147
+ error InsufficientEthBalance();
148
+ error EthTransferFailed();
149
+ error InvalidAddress();
150
+ error DepositDisabled();
151
+ error InsufficientCotiFee();
152
+ error BridgePaused();
153
+ error OracleTimestampMismatch(uint256 expected, uint256 actual);
154
+ error PriceOracleNotSet();
155
+ error InvalidOraclePrice();
156
+ error OraclePriceStale(uint256 oracleLastUpdated, uint256 blockTimestamp, uint256 maxOracleAge);
157
+ error OracleLastUpdatedInFuture(uint256 lastUpdated);
158
+ error OracleMaxAgeZeroDisallowed();
159
+ error FeeRecipientNotSet();
160
+ error AddressBlacklisted(address account);
161
+
162
+ /// @notice Addresses blocked from depositing or withdrawing
163
+ mapping(address => bool) public blacklisted;
164
+
165
+ /// @notice Per-user native COTI credited when an ERC20 bridge excess refund could not be pushed to `msg.sender` (e.g. smart contract wallets).
166
+ /// @dev Indexed by the same address that called `deposit`/`withdraw`. Pull via {claimRefundableNativeExcess}; listen for {NativeRefundExcessPushFailed}.
167
+ mapping(address => uint256) public refundableNativeExcess;
168
+
169
+ event Blacklisted(address indexed account, address indexed by);
170
+ event UnBlacklisted(address indexed account, address indexed by);
171
+ event NativeRefundExcessPushFailed(address indexed user, uint256 amount);
172
+ event RefundableNativeExcessClaimed(address indexed user, uint256 amount);
173
+
174
+ // Limits errors
175
+ error InvalidLimitConfiguration();
176
+ error DepositBelowMinimum();
177
+ error DepositExceedsMaximum();
178
+ error WithdrawBelowMinimum();
179
+ error WithdrawExceedsMaximum();
180
+ error InvalidFee();
181
+ error InvalidFeeConfiguration();
182
+ error InsufficientAccumulatedFees();
183
+
184
+ /// @notice Emitted when a user deposits tokens
185
+ /// @param user Address of the user
186
+ /// @param grossAmount Total amount provided by the user before fees
187
+ /// @param netAmount Net amount credited to the user after fees
188
+ event Deposit(address indexed user, uint256 grossAmount, uint256 netAmount);
189
+
190
+ /// @notice Emitted when a user withdraws tokens
191
+ /// @param user Address of the user
192
+ /// @param grossAmount Total amount of private tokens burned / requested
193
+ /// @param netAmount Net public/native amount sent to the user after fees
194
+ event Withdraw(address indexed user, uint256 grossAmount, uint256 netAmount);
195
+
196
+ /// @notice Emitted when deposit/withdrawal limits are updated
197
+ event LimitsUpdated(
198
+ uint256 minDeposit,
199
+ uint256 maxDeposit,
200
+ uint256 minWithdraw,
201
+ uint256 maxWithdraw
202
+ );
203
+
204
+ /// @notice Emitted when accumulated fees are withdrawn
205
+ event FeesWithdrawn(address indexed to, uint256 amount);
206
+
207
+ /**
208
+ * @param _feeRecipient Non-zero recipient for swept native fees (immutable for contract lifetime—no setter)
209
+ * @param _rescueRecipient Non-zero recipient for emergency rescue paths (immutable for contract lifetime—no setter)
210
+ * @param _priceOracle Non-zero {ICotiPriceConsumer} used for dynamic fees (owner may later {setPriceOracle})
211
+ */
212
+ constructor(address _feeRecipient, address _rescueRecipient, address _priceOracle) Ownable() {
213
+ if (_feeRecipient == address(0)) revert InvalidAddress();
214
+ if (_rescueRecipient == address(0)) revert InvalidAddress();
215
+ if (_priceOracle == address(0)) revert InvalidAddress();
216
+ maxDepositAmount = type(uint256).max;
217
+ maxWithdrawAmount = type(uint256).max;
218
+ minDepositAmount = 1;
219
+ minWithdrawAmount = 1;
220
+ feeRecipient = _feeRecipient;
221
+ rescueRecipient = _rescueRecipient;
222
+ priceOracle = _priceOracle;
223
+ maxOracleAge = DEFAULT_MAX_ORACLE_AGE;
224
+
225
+ emit PriceOracleUpdated(address(0), _priceOracle);
226
+
227
+ _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
228
+ _grantRole(OPERATOR_ROLE, msg.sender);
229
+ }
230
+
231
+ modifier onlyOperator() {
232
+ _checkRole(OPERATOR_ROLE, msg.sender);
233
+ _;
234
+ }
235
+
236
+ function addOperator(address account) external onlyRole(DEFAULT_ADMIN_ROLE) {
237
+ if (account == address(0)) revert InvalidAddress();
238
+ _grantRole(OPERATOR_ROLE, account);
239
+ emit OperatorAdded(account, msg.sender);
240
+ }
241
+
242
+ function removeOperator(address account) external onlyRole(DEFAULT_ADMIN_ROLE) {
243
+ if (account == address(0)) revert InvalidAddress();
244
+ _revokeRole(OPERATOR_ROLE, account);
245
+ emit OperatorRemoved(account, msg.sender);
246
+ }
247
+
248
+ function isOperator(address account) external view returns (bool) {
249
+ return hasRole(OPERATOR_ROLE, account);
250
+ }
251
+
252
+ /**
253
+ * @notice Transfers `Ownable` ownership and resets `AccessControl` admins/operators in one step.
254
+ * @dev **Handover semantics:** Every address with `OPERATOR_ROLE` and every address with `DEFAULT_ADMIN_ROLE`
255
+ * (including the current owner) is revoked before `Ownable` transfers to `newOwner`, who then receives
256
+ * both `DEFAULT_ADMIN_ROLE` and `OPERATOR_ROLE`. Any prior operator-only keys lose privilege immediately;
257
+ * plan key ceremonies and off-chain runbooks so no service relies on a revoked operator after transfer.
258
+ * This prevents stale operators from coexisting with a new owner (hidden privileged actors).
259
+ */
260
+ function transferOwnership(address newOwner) public override onlyOwner {
261
+ if (newOwner == address(0)) revert InvalidAddress();
262
+
263
+ // Revoke all existing operators before transferring
264
+ uint256 operatorCount = getRoleMemberCount(OPERATOR_ROLE);
265
+ for (uint256 i = operatorCount; i > 0; i--) {
266
+ address op = getRoleMember(OPERATOR_ROLE, i - 1);
267
+ _revokeRole(OPERATOR_ROLE, op);
268
+ }
269
+
270
+ // Revoke all existing admins
271
+ uint256 adminCount = getRoleMemberCount(DEFAULT_ADMIN_ROLE);
272
+ for (uint256 i = adminCount; i > 0; i--) {
273
+ address admin = getRoleMember(DEFAULT_ADMIN_ROLE, i - 1);
274
+ _revokeRole(DEFAULT_ADMIN_ROLE, admin);
275
+ }
276
+
277
+ super.transferOwnership(newOwner);
278
+ _grantRole(DEFAULT_ADMIN_ROLE, newOwner);
279
+ _grantRole(OPERATOR_ROLE, newOwner);
280
+ }
281
+
282
+ /**
283
+ * @dev **Intentionally disabled** (reverts with a fixed message). `renounceOwnership` would leave `AccessControl`
284
+ * roles and admins in place while clearing `Ownable.owner`, producing ambiguous governance (`onlyOwner`
285
+ * vs `onlyRole`). Use {transferOwnership} to a burn/multisig address if governance must be vacated, after
286
+ * revoking roles through the normal owner-controlled flows this contract expects.
287
+ */
288
+ function renounceOwnership() public override onlyOwner {
289
+ revert("renounceOwnership disabled");
290
+ }
291
+
292
+ /**
293
+ * @notice Add an address to the blacklist, preventing deposits and withdrawals.
294
+ * @param account The address to blacklist
295
+ * @dev Only the owner can call this function.
296
+ */
297
+ function addToBlacklist(address account) external onlyOwner {
298
+ if (account == address(0)) revert InvalidAddress();
299
+ blacklisted[account] = true;
300
+ emit Blacklisted(account, msg.sender);
301
+ }
302
+
303
+ /**
304
+ * @notice Remove an address from the blacklist.
305
+ * @param account The address to remove
306
+ * @dev Only the owner can call this function.
307
+ */
308
+ function removeFromBlacklist(address account) external onlyOwner {
309
+ if (account == address(0)) revert InvalidAddress();
310
+ blacklisted[account] = false;
311
+ emit UnBlacklisted(account, msg.sender);
312
+ }
313
+
314
+ /**
315
+ * @dev Reverts if the caller is blacklisted. Applies to deposit, withdraw, and {claimRefundableNativeExcess}.
316
+ * Blacklisted addresses are intentionally **not** exempted on claim: policy treats them as abusive;
317
+ * credited {refundableNativeExcess} for that address remains until the owner removes the listing or
318
+ * another agreed process applies.
319
+ */
320
+ modifier notBlacklisted() {
321
+ if (blacklisted[msg.sender]) revert AddressBlacklisted(msg.sender);
322
+ _;
323
+ }
324
+
325
+ /**
326
+ * @notice Update deposit and withdrawal limits
327
+ * @dev Ensures min values are less than or equal to max values.
328
+ * Setting _maxDeposit or _maxWithdraw to 0 effectively disables deposits or withdrawals.
329
+ * Note: cross-parameter coherence (e.g. minDeposit after fee >= minWithdraw) cannot be
330
+ * validated on-chain because fees are dynamic and depend on the oracle price at transaction
331
+ * time, not at the time limits are set. The operator is responsible for ensuring that the
332
+ * smallest valid deposit mints at least the smallest valid withdrawal amount.
333
+ * @param _minDeposit New minimum deposit amount
334
+ * @param _maxDeposit New maximum deposit amount
335
+ * @param _minWithdraw New minimum withdrawal amount
336
+ * @param _maxWithdraw New maximum withdrawal amount
337
+ */
338
+ function setLimits(
339
+ uint256 _minDeposit,
340
+ uint256 _maxDeposit,
341
+ uint256 _minWithdraw,
342
+ uint256 _maxWithdraw
343
+ ) external onlyOwner {
344
+ if (_minDeposit > _maxDeposit) revert InvalidLimitConfiguration();
345
+ if (_minWithdraw > _maxWithdraw) revert InvalidLimitConfiguration();
346
+ minDepositAmount = _minDeposit;
347
+ maxDepositAmount = _maxDeposit;
348
+ minWithdrawAmount = _minWithdraw;
349
+ maxWithdrawAmount = _maxWithdraw;
350
+
351
+ emit LimitsUpdated(
352
+ _minDeposit,
353
+ _maxDeposit,
354
+ _minWithdraw,
355
+ _maxWithdraw
356
+ );
357
+ }
358
+
359
+ /**
360
+ * @notice Emergency stop — pause the bridge, preventing all deposits and withdrawals.
361
+ * @dev Only the owner can call this function. Pausing also gates rescue paths on derived contracts: once
362
+ * paused, the owner can move TVL via rescue (see contract @dev (3)). Use pause only with operational
363
+ * awareness of that combined authority.
364
+ */
365
+ function pause() external onlyOwner {
366
+ _pause();
367
+ }
368
+
369
+ /**
370
+ * @notice Unpause the bridge, allowing deposits and withdrawals again
371
+ * @dev Only the owner can call this function
372
+ */
373
+ function unpause() external onlyOwner {
374
+ _unpause();
375
+ }
376
+
377
+ /**
378
+ * @notice Check if a deposit amount is within configured limits
379
+ * @param amount The amount to check
380
+ * @dev Reverts if amount is below minimum or above maximum
381
+ */
382
+ function _checkDepositLimits(uint256 amount) internal view {
383
+ if (amount < minDepositAmount) revert DepositBelowMinimum();
384
+ if (amount > maxDepositAmount) revert DepositExceedsMaximum();
385
+ }
386
+
387
+ /**
388
+ * @notice Check if a withdrawal amount is within configured limits
389
+ * @param amount The amount to check
390
+ * @dev Reverts if amount is below minimum or exceeds maximum withdrawal limit
391
+ */
392
+ function _checkWithdrawLimits(uint256 amount) internal view {
393
+ if (amount < minWithdrawAmount) revert WithdrawBelowMinimum();
394
+ if (amount > maxWithdrawAmount) revert WithdrawExceedsMaximum();
395
+ }
396
+
397
+ /**
398
+ * @notice Toggle deposit functionality
399
+ * @param _enabled True to enable, false to disable
400
+ * @dev Only the operator can call this function
401
+ */
402
+ function setIsDepositEnabled(bool _enabled) external onlyOperator {
403
+ isDepositEnabled = _enabled;
404
+ emit DepositEnabledUpdated(_enabled, msg.sender);
405
+ }
406
+
407
+ function _requirePriceOracle() internal view {
408
+ if (priceOracle == address(0)) revert PriceOracleNotSet();
409
+ }
410
+
411
+ function _requirePositiveOracleRate(uint256 rate) internal pure {
412
+ if (rate == 0) revert InvalidOraclePrice();
413
+ }
414
+
415
+ /**
416
+ * @dev Credits `user` when the ERC20 bridge’s push-refund of native excess after fee collection returns false
417
+ * (common with smart contract accounts / AA wallets that reject unsolicited ETH, or `receive`/`fallback`
418
+ * reverts). Funds remain on the bridge until {claimRefundableNativeExcess}. UIs should watch
419
+ * {NativeRefundExcessPushFailed} and prompt the same `user` to claim; the amount is not in
420
+ * {accumulatedCotiFees} and cannot be swept as protocol fees.
421
+ */
422
+ function _creditRefundableNativeExcess(address user, uint256 amount) internal {
423
+ refundableNativeExcess[user] += amount;
424
+ emit NativeRefundExcessPushFailed(user, amount);
425
+ }
426
+
427
+ /**
428
+ * @notice Pull native COTI previously credited when the ERC20 bridge could not push the fee excess to you.
429
+ * @dev Same push pattern as the original refund: `msg.sender.call{value: amount}`. If your wallet still
430
+ * rejects ETH, the call reverts with {EthTransferFailed} and your credit is restored so you can try
431
+ * again from an address that accepts native transfers (the protocol does not support forwarding to a
432
+ * third-party payout address). Not gated by {whenPaused}; {notBlacklisted} applies ({AddressBlacklisted})—
433
+ * blacklisted callers cannot pull credits by design (see {notBlacklisted}).
434
+ */
435
+ function claimRefundableNativeExcess() external nonReentrant notBlacklisted {
436
+ uint256 amount = refundableNativeExcess[msg.sender];
437
+ if (amount == 0) revert AmountZero();
438
+ refundableNativeExcess[msg.sender] = 0;
439
+ if (address(this).balance < amount) revert InsufficientEthBalance();
440
+ (bool success, ) = msg.sender.call{value: amount}("");
441
+ if (!success) {
442
+ refundableNativeExcess[msg.sender] = amount;
443
+ revert EthTransferFailed();
444
+ }
445
+ emit RefundableNativeExcessClaimed(msg.sender, amount);
446
+ }
447
+
448
+ /**
449
+ * @notice Reject oracle rows that are too old vs `block.timestamp` per {maxOracleAge}.
450
+ * @dev {maxOracleAge} is always non-zero in normal configuration ({setMaxOracleAge} forbids zero).
451
+ */
452
+ function _requireOracleFreshness(uint256 lastUpdated) internal view {
453
+ uint256 maxAge = maxOracleAge;
454
+ if (lastUpdated > block.timestamp) revert OracleLastUpdatedInFuture(lastUpdated);
455
+ uint256 nowTs = block.timestamp;
456
+ if (nowTs - lastUpdated > maxAge) revert OraclePriceStale(lastUpdated, nowTs, maxAge);
457
+ }
458
+
459
+ /**
460
+ * @notice Validate oracle timestamps for both COTI and a bridged token.
461
+ * @dev Strict equality: on-chain `lastUpdated` for COTI and for `tokenSymbol` must exactly equal the
462
+ * `expected*` values supplied by the client. That binds execution to the same Band row the user
463
+ * saw when calling the estimate view; if the feed publishes a newer row before inclusion, the check
464
+ * reverts with {OracleTimestampMismatch} so price cannot change under the user without a visible revert.
465
+ * This strict binding is **intentional** (no relaxation): with a typical ~30 minute oracle cadence and
466
+ * {maxOracleAge} buffer, users have a long window to sign and broadcast the same row; we avoid any path
467
+ * where the UI shows one Band row and execution silently uses a newer price.
468
+ * Failures are timing/race issues (mempool delay vs oracle refresh cadence), not third-party griefing.
469
+ * Integrators: call estimate immediately before building the tx; pass returned timestamps unchanged into
470
+ * deposit/withdraw; on mismatch, re-estimate and resubmit; avoid submit across a refresh boundary (COTI UI
471
+ * blocks ~10s before a scheduled tick—mirror that); simulate right before broadcast. {_requireOracleFreshness}
472
+ * still enforces {maxOracleAge} on the matched row.
473
+ * @param expectedCotiTimestamp COTI `lastUpdated` from the user's latest estimate (must equal on-chain).
474
+ * @param expectedTokenTimestamp Token `lastUpdated` from the user's latest estimate (must equal on-chain).
475
+ * @param tokenSymbol The Band oracle symbol for the bridged token (native bridge uses `"COTI"` for both).
476
+ */
477
+ function _validateOracleTimestamps(
478
+ uint256 expectedCotiTimestamp,
479
+ uint256 expectedTokenTimestamp,
480
+ string memory tokenSymbol
481
+ ) internal view {
482
+ _requirePriceOracle();
483
+ (, uint256 cotiLastUpdated,) = ICotiPriceConsumer(priceOracle).getPriceWithMeta("COTI");
484
+ if (cotiLastUpdated != expectedCotiTimestamp) revert OracleTimestampMismatch(expectedCotiTimestamp, cotiLastUpdated);
485
+ _requireOracleFreshness(cotiLastUpdated);
486
+ (, uint256 tokenLastUpdated,) = ICotiPriceConsumer(priceOracle).getPriceWithMeta(tokenSymbol);
487
+ if (tokenLastUpdated != expectedTokenTimestamp) revert OracleTimestampMismatch(expectedTokenTimestamp, tokenLastUpdated);
488
+ _requireOracleFreshness(tokenLastUpdated);
489
+ }
490
+
491
+ /**
492
+ * @notice Calculate the dynamic fee using the floor/cap formula
493
+ * @param percentageFeeCoti The percentage-based fee component in COTI
494
+ * @param fixedFee The minimum fee floor in COTI
495
+ * @param maxFee The maximum fee cap in COTI
496
+ * @return The computed fee: min(max(fixedFee, percentageFeeCoti), maxFee)
497
+ */
498
+ function _calculateDynamicFee(
499
+ uint256 percentageFeeCoti,
500
+ uint256 fixedFee,
501
+ uint256 maxFee
502
+ ) internal pure returns (uint256) {
503
+ uint256 fee = percentageFeeCoti > fixedFee ? percentageFeeCoti : fixedFee;
504
+ return fee > maxFee ? maxFee : fee;
505
+ }
506
+
507
+ /**
508
+ * @notice Estimate functions are declared in derived contracts (Native and ERC20 bridges)
509
+ * with different return signatures:
510
+ * - Native: returns (fee, lastUpdated, blockTimestamp)
511
+ * - ERC20: returns (fee, cotiLastUpdated, tokenLastUpdated, blockTimestamp)
512
+ */
513
+
514
+ /**
515
+ * @notice Set the deposit dynamic fee parameters
516
+ * @param _fixedFee New deposit fee floor in COTI wei
517
+ * @param _percentageBps New deposit percentage (max MAX_FEE_UNITS = 10%)
518
+ * @param _maxFee New deposit fee cap in COTI wei
519
+ * @dev Only the operator can call this function
520
+ */
521
+ function setDepositDynamicFee(
522
+ uint256 _fixedFee,
523
+ uint256 _percentageBps,
524
+ uint256 _maxFee
525
+ ) external onlyOperator {
526
+ if (_maxFee == 0) revert InvalidFeeConfiguration();
527
+ if (_fixedFee > _maxFee) revert InvalidFeeConfiguration();
528
+ if (_percentageBps > MAX_FEE_UNITS) revert InvalidFee();
529
+ depositFixedFee = _fixedFee;
530
+ depositPercentageBps = _percentageBps;
531
+ depositMaxFee = _maxFee;
532
+ emit DynamicFeeUpdated("deposit", _fixedFee, _percentageBps, _maxFee);
533
+ }
534
+
535
+ /**
536
+ * @notice Set the withdraw dynamic fee parameters
537
+ * @param _fixedFee New withdraw fee floor in COTI wei
538
+ * @param _percentageBps New withdraw percentage (max MAX_FEE_UNITS = 10%)
539
+ * @param _maxFee New withdraw fee cap in COTI wei
540
+ * @dev Only the operator can call this function
541
+ */
542
+ function setWithdrawDynamicFee(
543
+ uint256 _fixedFee,
544
+ uint256 _percentageBps,
545
+ uint256 _maxFee
546
+ ) external onlyOperator {
547
+ if (_maxFee == 0) revert InvalidFeeConfiguration();
548
+ if (_fixedFee > _maxFee) revert InvalidFeeConfiguration();
549
+ if (_percentageBps > MAX_FEE_UNITS) revert InvalidFee();
550
+ withdrawFixedFee = _fixedFee;
551
+ withdrawPercentageBps = _percentageBps;
552
+ withdrawMaxFee = _maxFee;
553
+ emit DynamicFeeUpdated("withdraw", _fixedFee, _percentageBps, _maxFee);
554
+ }
555
+
556
+ /**
557
+ * @notice Set the price oracle address
558
+ * @param _oracle Address of the CotiPriceConsumer contract
559
+ * @dev Only the owner can call this function
560
+ */
561
+ function setPriceOracle(address _oracle) external onlyOwner {
562
+ if (_oracle == address(0)) revert InvalidAddress();
563
+ address oldOracle = priceOracle;
564
+ priceOracle = _oracle;
565
+ emit PriceOracleUpdated(oldOracle, _oracle);
566
+ }
567
+
568
+ /**
569
+ * @notice Set the maximum allowed age of oracle `lastUpdated` (seconds) relative to `block.timestamp`.
570
+ * @param _maxOracleAge Must be non-zero. Default after deploy is {DEFAULT_MAX_ORACLE_AGE} (30 min cadence + 5 min buffer).
571
+ * @dev Zero is rejected so production cannot accidentally turn off staleness bounds; for very lenient test
572
+ * environments use a large finite value instead.
573
+ */
574
+ function setMaxOracleAge(uint256 _maxOracleAge) external onlyOwner {
575
+ if (_maxOracleAge == 0) revert OracleMaxAgeZeroDisallowed();
576
+ maxOracleAge = _maxOracleAge;
577
+ emit MaxOracleAgeUpdated(_maxOracleAge, msg.sender);
578
+ }
579
+
580
+ event CotiFeesWithdrawn(address indexed feeRecipient, uint256 amount);
581
+
582
+ /**
583
+ * @notice Withdraw accumulated native COTI fees to the predefined feeRecipient
584
+ * @param amount Amount of native COTI fees to withdraw
585
+ * @dev Only the owner can call this function.
586
+ */
587
+ function withdrawCotiFees(uint256 amount) external onlyOwner nonReentrant {
588
+ if (feeRecipient == address(0)) revert FeeRecipientNotSet();
589
+ if (amount == 0) revert AmountZero();
590
+ if (amount > accumulatedCotiFees) revert InsufficientAccumulatedFees();
591
+ if (amount > address(this).balance) revert InsufficientEthBalance();
592
+
593
+ accumulatedCotiFees -= amount;
594
+
595
+ (bool success, ) = feeRecipient.call{value: amount}("");
596
+ if (!success) revert EthTransferFailed();
597
+
598
+ emit CotiFeesWithdrawn(feeRecipient, amount);
599
+ }
600
+ }