@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,316 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.19;
3
+
4
+ import "./PrivacyBridge.sol";
5
+ import "@openzeppelin/contracts/utils/math/Math.sol";
6
+ import "../token/PrivateERC20/tokens/PrivateCOTI.sol";
7
+
8
+ /**
9
+ * @title PrivacyBridgeCotiNative
10
+ * @notice Bridge contract for converting between native COTI and privacy-preserving COTI.p tokens
11
+ * @dev Withdraw pulls private balance via `IPrivateERC20(address(privateCoti)).transferFrom` so the call matches
12
+ * the canonical {IPrivateERC20} surface (`contracts/token/PrivateERC20/IPrivateERC20.sol`) while `privateCoti`
13
+ * remains the concrete {PrivateCOTI} type for mint/burn. Deploy `_privateCoti` as that implementation (or a
14
+ * fully ABI-compatible successor); do not point at arbitrary ERC-20s.
15
+ *
16
+ * **Two native deposit paths (document for wallets / indexers):**
17
+ * - {deposit(uint256,uint256)}: user passes `cotiOracleTimestamp` and `tokenOracleTimestamp` (same value
18
+ * twice for `"COTI"`); {_validateOracleTimestamps} enforces they match the on-chain Band row—same quote row
19
+ * as {estimateDepositFee}. Use this when you need binding between off-chain estimate and execution.
20
+ * - {receive} / plain ETH send: uses {_directDeposit}; fee still uses {_computeCotiFee} with staleness
21
+ * ({_requireOracleFreshness}) but **does not** require equality to estimate timestamps—no prior estimate row
22
+ * is pinned. Prefer explicit {deposit} for predictable “what I quoted is what executes.”
23
+ *
24
+ * **Unsolicited native:** balance can increase via `selfdestruct` or other forced transfers without invoking
25
+ * {receive}; that ETH does not mint private tokens and does not update {PrivacyBridge.totalUserLiability}.
26
+ */
27
+ contract PrivacyBridgeCotiNative is PrivacyBridge {
28
+ PrivateCOTI public privateCoti;
29
+
30
+ event NativeRescued(address indexed to, uint256 amount);
31
+
32
+ // Scaling factor removed (using native 18 decimals due to uint256 upgrade)
33
+
34
+ /**
35
+ * @notice Initialize the Native Bridge
36
+ * @param _privateCoti Address of the PrivateCoti token contract
37
+ * @param _priceOracle Non-zero price oracle (see {PrivacyBridge}'s constructor)
38
+ */
39
+ constructor(address _privateCoti, address _feeRecipient, address _rescueRecipient, address _priceOracle) PrivacyBridge(_feeRecipient, _rescueRecipient, _priceOracle) {
40
+ if (_privateCoti == address(0)) revert InvalidAddress();
41
+ privateCoti = PrivateCOTI(_privateCoti);
42
+ }
43
+
44
+ /**
45
+ * @dev Native COTI fee math + one {getPriceWithMeta("COTI")} read. Used by {_computeCotiFee} and
46
+ * {estimateDepositFee}/{estimateWithdrawFee}. Each {Math.mulDiv} truncates toward zero (see
47
+ * {PrivacyBridge.FEE_DIVISOR} NatSpec). Extreme `cotiAmount`×`cotiUsdRate` values can make {Math.mulDiv}
48
+ * revert—keep amounts within configured max deposit/withdraw limits.
49
+ * @param cotiAmount Amount in COTI wei the fee is computed for
50
+ * @param fixedFee Minimum fee floor in COTI wei
51
+ * @param percentageBps Percentage parameter scaled by {PrivacyBridge.FEE_DIVISOR}
52
+ * @param maxFee Maximum fee cap in COTI wei
53
+ * @return fee Computed fee in COTI wei
54
+ * @return cotiLastUpdated COTI oracle row `lastUpdated`
55
+ * @return blockTimestamp Third field from the COTI oracle row
56
+ */
57
+ function _computeCotiFeeAndMeta(
58
+ uint256 cotiAmount,
59
+ uint256 fixedFee,
60
+ uint256 percentageBps,
61
+ uint256 maxFee
62
+ ) internal view returns (uint256 fee, uint256 cotiLastUpdated, uint256 blockTimestamp) {
63
+ _requirePriceOracle();
64
+ (uint256 cotiUsdRate, uint256 cotiLU, uint256 cotiBts) = ICotiPriceConsumer(priceOracle).getPriceWithMeta("COTI");
65
+ _requirePositiveOracleRate(cotiUsdRate);
66
+ _requireOracleFreshness(cotiLU);
67
+ uint256 txValueUsd = Math.mulDiv(cotiAmount, cotiUsdRate, 1e18);
68
+ uint256 percentageFeeUsd = Math.mulDiv(txValueUsd, percentageBps, FEE_DIVISOR);
69
+ uint256 percentageFeeCoti = Math.mulDiv(percentageFeeUsd, 1e18, cotiUsdRate);
70
+ fee = _calculateDynamicFee(percentageFeeCoti, fixedFee, maxFee);
71
+ cotiLastUpdated = cotiLU;
72
+ blockTimestamp = cotiBts;
73
+ }
74
+
75
+ function _computeCotiFee(
76
+ uint256 cotiAmount,
77
+ uint256 fixedFee,
78
+ uint256 percentageBps,
79
+ uint256 maxFee
80
+ ) internal view returns (uint256) {
81
+ (uint256 f,,) = _computeCotiFeeAndMeta(cotiAmount, fixedFee, percentageBps, maxFee);
82
+ return f;
83
+ }
84
+
85
+ /**
86
+ * @notice Simulate fee calculation for native COTI with arbitrary parameters.
87
+ * @dev Public view — allows frontends/operators to preview fees with custom fee params.
88
+ * Reads live COTI oracle price but accepts custom fee configuration.
89
+ * @param cotiAmount The COTI amount to compute fee for (wei; very large values can revert in fee math)
90
+ * @param fixedFee The minimum fee floor in COTI wei
91
+ * @param percentageBps The percentage in basis points (relative to {FEE_DIVISOR})
92
+ * @param maxFee The maximum fee cap in COTI wei
93
+ * @return The computed fee in COTI wei
94
+ */
95
+ function computeCotiFee(
96
+ uint256 cotiAmount,
97
+ uint256 fixedFee,
98
+ uint256 percentageBps,
99
+ uint256 maxFee
100
+ ) external view returns (uint256) {
101
+ return _computeCotiFee(cotiAmount, fixedFee, percentageBps, maxFee);
102
+ }
103
+
104
+ /**
105
+ * @notice Estimate the deposit fee in COTI for a given COTI amount
106
+ * @param cotiAmount The amount of native COTI to deposit (wei; very large values can revert in fee math)
107
+ * @return fee The estimated fee in COTI wei
108
+ * @return cotiLastUpdated COTI oracle data last update timestamp
109
+ * @return blockTimestamp Third field from the COTI oracle row (same as pre-refactor behavior)
110
+ * @dev Use `cotiLastUpdated` for **both** `cotiOracleTimestamp` and `tokenOracleTimestamp` on {deposit}/{withdraw}
111
+ * (native bridge validates `"COTI"` twice). See {PrivacyBridge._validateOracleTimestamps}.
112
+ */
113
+ function estimateDepositFee(uint256 cotiAmount) external view returns (uint256 fee, uint256 cotiLastUpdated, uint256 blockTimestamp) {
114
+ (fee, cotiLastUpdated, blockTimestamp) = _computeCotiFeeAndMeta(
115
+ cotiAmount,
116
+ depositFixedFee,
117
+ depositPercentageBps,
118
+ depositMaxFee
119
+ );
120
+ }
121
+
122
+ /**
123
+ * @notice Estimate the withdrawal fee in COTI for a given COTI amount
124
+ * @param cotiAmount The amount of native COTI to withdraw (wei; very large values can revert in fee math)
125
+ * @return fee The estimated fee in COTI wei
126
+ * @return cotiLastUpdated COTI oracle data last update timestamp
127
+ * @return blockTimestamp Third field from the COTI oracle row (same as pre-refactor behavior)
128
+ * @dev Same timestamp usage as {estimateDepositFee} for the subsequent {withdraw}.
129
+ */
130
+ function estimateWithdrawFee(uint256 cotiAmount) external view returns (uint256 fee, uint256 cotiLastUpdated, uint256 blockTimestamp) {
131
+ (fee, cotiLastUpdated, blockTimestamp) = _computeCotiFeeAndMeta(
132
+ cotiAmount,
133
+ withdrawFixedFee,
134
+ withdrawPercentageBps,
135
+ withdrawMaxFee
136
+ );
137
+ }
138
+
139
+ /**
140
+ * @notice Internal function to handle deposits
141
+ * @param sender Address of the depositor
142
+ */
143
+ function _deposit(address sender, uint256 cotiOracleTimestamp, uint256 tokenOracleTimestamp) internal {
144
+ if (!isDepositEnabled) revert DepositDisabled();
145
+ if (msg.value == 0) revert AmountZero();
146
+
147
+ _checkDepositLimits(msg.value);
148
+ _validateOracleTimestamps(cotiOracleTimestamp, tokenOracleTimestamp, "COTI");
149
+
150
+ // Compute dynamic fee in COTI
151
+ uint256 fee = _computeCotiFee(msg.value, depositFixedFee, depositPercentageBps, depositMaxFee);
152
+ uint256 netAmount = msg.value - fee;
153
+ if (netAmount == 0) revert AmountZero();
154
+
155
+ accumulatedCotiFees += fee;
156
+
157
+ totalUserLiability += netAmount;
158
+ privateCoti.mint(sender, netAmount);
159
+
160
+ // Emit gross deposit amount and net private tokens minted
161
+ emit Deposit(sender, msg.value, netAmount);
162
+ }
163
+
164
+ /**
165
+ * @notice Deposit native COTI to receive private COTI (COTI.p)
166
+ * @param cotiOracleTimestamp COTI `lastUpdated` from the latest `estimateDepositFee` (must still equal on-chain at execution).
167
+ * @param tokenOracleTimestamp Same value as `cotiOracleTimestamp` for this bridge (both checks use `"COTI"`).
168
+ * @dev User sends native COTI with the transaction. Oracle races: {OracleTimestampMismatch} — re-estimate; see {_validateOracleTimestamps}.
169
+ */
170
+ function deposit(uint256 cotiOracleTimestamp, uint256 tokenOracleTimestamp) external payable nonReentrant whenNotPaused notBlacklisted {
171
+ _deposit(msg.sender, cotiOracleTimestamp, tokenOracleTimestamp);
172
+ }
173
+
174
+ /**
175
+ * @notice Withdraw native COTI by burning private COTI
176
+ * @param amount Amount of private COTI to burn
177
+ * @param cotiOracleTimestamp COTI `lastUpdated` from the latest `estimateWithdrawFee` (must still equal on-chain at execution).
178
+ * @param tokenOracleTimestamp Same value as `cotiOracleTimestamp` for this bridge.
179
+ * @dev User must have approved the bridge to spend their private tokens. Oracle rules: {_validateOracleTimestamps}.
180
+ */
181
+ function withdraw(uint256 amount, uint256 cotiOracleTimestamp, uint256 tokenOracleTimestamp) external nonReentrant whenNotPaused notBlacklisted {
182
+ _withdraw(msg.sender, amount, cotiOracleTimestamp, tokenOracleTimestamp);
183
+ }
184
+
185
+ function _withdraw(
186
+ address to,
187
+ uint256 amount,
188
+ uint256 cotiOracleTimestamp,
189
+ uint256 tokenOracleTimestamp
190
+ ) internal {
191
+ if (amount == 0) revert AmountZero();
192
+ _checkWithdrawLimits(amount);
193
+ _validateOracleTimestamps(cotiOracleTimestamp, tokenOracleTimestamp, "COTI");
194
+
195
+ // Compute dynamic withdrawal fee in COTI
196
+ uint256 fee = _computeCotiFee(amount, withdrawFixedFee, withdrawPercentageBps, withdrawMaxFee);
197
+ uint256 publicAmount = amount - fee;
198
+ if (publicAmount == 0) revert AmountZero();
199
+
200
+ accumulatedCotiFees += fee;
201
+
202
+ if (address(this).balance < publicAmount)
203
+ revert InsufficientEthBalance();
204
+
205
+ // Extinguish liability for the full private amount burned (fee stays with bridge as native revenue).
206
+ totalUserLiability -= amount;
207
+
208
+ // Pull and burn private tokens
209
+ IPrivateERC20(address(privateCoti)).transferFrom(
210
+ msg.sender,
211
+ address(this),
212
+ amount
213
+ );
214
+ privateCoti.burn(amount);
215
+
216
+ (bool success, ) = to.call{value: publicAmount}("");
217
+ if (!success) revert EthTransferFailed();
218
+
219
+ emit Withdraw(to, amount, publicAmount);
220
+ }
221
+
222
+ /**
223
+ * @notice Internal deposit without binding to a prior estimate’s oracle `lastUpdated` snapshot.
224
+ * @dev Used by {receive}. Fee uses {_computeCotiFee}, which still enforces: oracle configured
225
+ * ({PriceOracleNotSet}), non-zero COTI/USD rate ({InvalidOraclePrice}), and max age of
226
+ * `lastUpdated` when {PrivacyBridge.maxOracleAge} is set ({OraclePriceStale} /
227
+ * {OracleLastUpdatedInFuture}). What plain sends do **not** do is equality to timestamps
228
+ * passed into {deposit} from an off-chain estimate—users who need that binding should call {deposit}.
229
+ */
230
+ function _directDeposit(address sender) internal {
231
+ if (!isDepositEnabled) revert DepositDisabled();
232
+ if (msg.value == 0) revert AmountZero();
233
+
234
+ _checkDepositLimits(msg.value);
235
+
236
+ uint256 fee = _computeCotiFee(msg.value, depositFixedFee, depositPercentageBps, depositMaxFee);
237
+ uint256 netAmount = msg.value - fee;
238
+ if (netAmount == 0) revert AmountZero();
239
+
240
+ accumulatedCotiFees += fee;
241
+
242
+ totalUserLiability += netAmount;
243
+ privateCoti.mint(sender, netAmount);
244
+
245
+ emit Deposit(sender, msg.value, netAmount);
246
+ }
247
+
248
+ /**
249
+ * @notice Fallback for plain native transfers: same fee path as {_directDeposit}.
250
+ * @dev See {_directDeposit}: zero/stale oracle rates are rejected via {_computeCotiFee}; use {deposit}
251
+ * when you must match `lastUpdated` from {estimateDepositFee} to the on-chain row (see {_validateOracleTimestamps}).
252
+ */
253
+ receive() external payable nonReentrant whenNotPaused notBlacklisted {
254
+ _directDeposit(msg.sender);
255
+ }
256
+
257
+ /**
258
+ * @notice Get the native COTI balance held by the bridge
259
+ * @return The contract's balance in native units (wei-equivalent)
260
+ */
261
+ function getBridgeBalance() external view returns (uint256) {
262
+ return address(this).balance;
263
+ }
264
+
265
+ /**
266
+ * @notice Withdraw accumulated fees to feeRecipient (Native implementation)
267
+ * @param amount Amount of fees to withdraw
268
+ * @dev Only the owner can call this function
269
+ */
270
+ function withdrawFees(
271
+ uint256 amount
272
+ ) external onlyOwner nonReentrant {
273
+ if (feeRecipient == address(0)) revert FeeRecipientNotSet();
274
+ if (amount == 0) revert AmountZero();
275
+ if (amount > accumulatedCotiFees) revert InsufficientAccumulatedFees();
276
+ if (amount > address(this).balance) revert InsufficientEthBalance();
277
+
278
+ accumulatedCotiFees -= amount;
279
+
280
+ // Transfer native COTI tokens to feeRecipient
281
+ (bool success, ) = feeRecipient.call{value: amount}("");
282
+ if (!success) revert EthTransferFailed();
283
+
284
+ emit FeesWithdrawn(feeRecipient, amount);
285
+ }
286
+
287
+ /**
288
+ * @notice Move native COTI from this bridge to {rescueRecipient} while the bridge is paused.
289
+ * @dev Emergency / migration path: sends up to `amount` (typically the full {address(this).balance}) to
290
+ * {rescueRecipient}. That balance can include all user-deposited native liquidity and unswept fee
291
+ * float—there is no on-chain carve-out that keeps “user principal” behind. Intended for bug recovery
292
+ * or handover to a new bridge; a malicious or compromised owner who has paused can drain TVL to
293
+ * {rescueRecipient} in one or more calls. See {PrivacyBridge} contract-level @dev (3) for governance
294
+ * mitigations (multisig, timelock, monitoring). After a partial rescue, {accumulatedCotiFees} is capped
295
+ * to the remaining balance so fee accounting cannot exceed what is still on the contract. {totalUserLiability}
296
+ * is **not** adjusted: rescue only moves native to {rescueRecipient}; it does not burn private tokens or
297
+ * reduce user obligations on this contract, so the counter may exceed {address(this).balance} until a
298
+ * separate migration makes users whole.
299
+ * @param amount Amount of native currency to send (often the full balance for migration).
300
+ */
301
+ function rescueNative(uint256 amount) external onlyOwner nonReentrant whenPaused {
302
+ if (amount == 0) revert AmountZero();
303
+ if (amount > address(this).balance) revert InsufficientEthBalance();
304
+
305
+ (bool success, ) = rescueRecipient.call{value: amount}("");
306
+ if (!success) revert EthTransferFailed();
307
+
308
+ uint256 remaining = address(this).balance;
309
+ if (accumulatedCotiFees > remaining) {
310
+ accumulatedCotiFees = remaining;
311
+ }
312
+
313
+ emit NativeRescued(rescueRecipient, amount);
314
+ }
315
+
316
+ }
@@ -0,0 +1,333 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.19;
3
+
4
+ import "./PrivacyBridge.sol";
5
+ import "@openzeppelin/contracts/utils/math/Math.sol";
6
+ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
7
+ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
8
+ import "../token/PrivateERC20/IPrivateERC20.sol";
9
+
10
+ /// @dev Minimal interface to read decimals from tokens without modifying IPrivateERC20
11
+ interface IHasDecimals {
12
+ function decimals() external view returns (uint8);
13
+ }
14
+
15
+ /**
16
+ * @dev Abstract base contract for ERC20 Token Privacy Bridges
17
+ * @dev Handles the logic for bridging ERC20 tokens to their private counterparts.
18
+ * @dev The public ERC20 must match standard transfer semantics: {safeTransferFrom} of `amount` must
19
+ * increase the bridge balance by exactly `amount` ({UnexpectedTransferBalance} otherwise). This
20
+ * rejects common fee-on-transfer / deflationary patterns. Rebasing, blacklist hooks, and other
21
+ * non-standard behavior remain unsupported—deployment must still use a suitable asset.
22
+ * @dev **Private token:** The constructor stores `_privateToken` as {IPrivateERC20} from
23
+ * `contracts/token/PrivateERC20/IPrivateERC20.sol` (same `pragma` family as this contract). Integrators should
24
+ * bind ABIs/codegen to that canonical interface in this repo; alternate compiler pipelines (e.g. via-IR-only)
25
+ * should still target the same ABI, not ad-hoc casts to incompatible shapes.
26
+ */
27
+ abstract contract PrivacyBridgeERC20 is PrivacyBridge {
28
+ using SafeERC20 for IERC20;
29
+
30
+ /// @notice The public ERC20 token being bridged (e.g., USDC, WETH)
31
+ IERC20 public token;
32
+
33
+ /// @notice Private token contract being minted/burned
34
+ IPrivateERC20 public privateToken;
35
+
36
+ /// @notice Band oracle symbol for the bridged token (e.g., "ETH", "WBTC", "ADA", "USDC", "USDT")
37
+ string public tokenSymbol;
38
+
39
+ /// @notice Cached ERC20 decimals (matches private token; set in constructor).
40
+ uint8 internal immutable bridgedTokenDecimals;
41
+
42
+ error InvalidTokenAddress();
43
+ error InvalidPrivateTokenAddress();
44
+ error CannotRescueBridgeToken();
45
+ error InvalidScalingFactor();
46
+ error AmountTooLarge();
47
+ error AmountTooSmall();
48
+ error InsufficientBridgeLiquidity();
49
+ error TokenTransferFailed();
50
+ error InvalidTokenSender();
51
+ error NativeFeeRequiredForTransferAndCallWithdraw();
52
+ error DecimalsMismatch();
53
+ /// @notice Pulled balance increase did not match `amount` (e.g. fee-on-transfer or deflationary token).
54
+ error UnexpectedTransferBalance(uint256 expected, uint256 received);
55
+ event ERC20Rescued(address indexed token, address indexed to, uint256 amount);
56
+
57
+ function _computeErc20Fee(
58
+ uint256 tokenAmount,
59
+ uint256 fixedFee,
60
+ uint256 percentageBps,
61
+ uint256 maxFee
62
+ ) internal view returns (uint256) {
63
+ (uint256 fee,,,) = _computeErc20FeeAndMeta(tokenAmount, fixedFee, percentageBps, maxFee, tokenSymbol, bridgedTokenDecimals);
64
+ return fee;
65
+ }
66
+
67
+ /**
68
+ * @notice Simulate fee calculation for any token symbol and decimals.
69
+ * @dev Public view — allows frontends/operators to preview fees with arbitrary parameters.
70
+ * Reads live oracle prices but accepts custom fee params and token config.
71
+ * @param tokenAmount The token amount to simulate fee for (raw units; very large values can revert in fee math)
72
+ * @param fixedFee The minimum fee floor in COTI wei
73
+ * @param percentageBps The percentage in basis points (relative to {FEE_DIVISOR})
74
+ * @param maxFee The maximum fee cap in COTI wei
75
+ * @param _tokenSymbol The Band oracle symbol (e.g. "ETH", "WBTC", "ADA")
76
+ * @param _tokenDecimals The decimal precision of the token (e.g. 18, 8, 6)
77
+ * @return The computed fee in native COTI (18 decimals)
78
+ */
79
+ function computeErc20Fee(
80
+ uint256 tokenAmount,
81
+ uint256 fixedFee,
82
+ uint256 percentageBps,
83
+ uint256 maxFee,
84
+ string calldata _tokenSymbol,
85
+ uint8 _tokenDecimals
86
+ ) external view returns (uint256) {
87
+ (uint256 fee,,,) = _computeErc20FeeAndMeta(tokenAmount, fixedFee, percentageBps, maxFee, _tokenSymbol, _tokenDecimals);
88
+ return fee;
89
+ }
90
+
91
+ /**
92
+ * @dev ERC20 fee math + two {getPriceWithMeta} reads (token then COTI). Used by {_computeErc20Fee}
93
+ * and {estimateDepositFee}/{estimateWithdrawFee}. Each {Math.mulDiv} step truncates toward zero
94
+ * (see {PrivacyBridge.FEE_DIVISOR} NatSpec). Extreme `tokenAmount`×`tokenUsdRate` values can make
95
+ * {Math.mulDiv} revert—keep amounts within configured max deposit/withdraw limits.
96
+ */
97
+ function _computeErc20FeeAndMeta(
98
+ uint256 tokenAmount,
99
+ uint256 fixedFee,
100
+ uint256 percentageBps,
101
+ uint256 maxFee,
102
+ string memory oracleTokenSymbol,
103
+ uint8 tokenDecimals
104
+ )
105
+ internal
106
+ view
107
+ returns (uint256 fee, uint256 cotiLastUpdated, uint256 tokenLastUpdated, uint256 blockTimestamp)
108
+ {
109
+ _requirePriceOracle();
110
+ ICotiPriceConsumer oracle = ICotiPriceConsumer(priceOracle);
111
+ (uint256 tokenUsdRate, uint256 tokenLU,) = oracle.getPriceWithMeta(oracleTokenSymbol);
112
+ (uint256 cotiUsdRate, uint256 cotiLU, uint256 cotiBts) = oracle.getPriceWithMeta("COTI");
113
+ _requirePositiveOracleRate(tokenUsdRate);
114
+ _requirePositiveOracleRate(cotiUsdRate);
115
+ _requireOracleFreshness(tokenLU);
116
+ _requireOracleFreshness(cotiLU);
117
+ uint256 txValueUsd = Math.mulDiv(tokenAmount, tokenUsdRate, 10 ** uint256(tokenDecimals));
118
+ uint256 percentageFeeUsd = Math.mulDiv(txValueUsd, percentageBps, FEE_DIVISOR);
119
+ uint256 percentageFeeCoti = Math.mulDiv(percentageFeeUsd, 1e18, cotiUsdRate);
120
+ fee = _calculateDynamicFee(percentageFeeCoti, fixedFee, maxFee);
121
+ cotiLastUpdated = cotiLU;
122
+ tokenLastUpdated = tokenLU;
123
+ blockTimestamp = cotiBts;
124
+ }
125
+
126
+ /**
127
+ * @notice Estimate the deposit fee in COTI for a given token amount
128
+ * @param tokenAmount The amount of ERC20 tokens to deposit (raw token units; very large values can revert in fee math)
129
+ * @return fee The estimated fee in native COTI (18 decimals)
130
+ * @return cotiLastUpdated COTI oracle data last update timestamp
131
+ * @return tokenLastUpdated Token oracle data last update timestamp
132
+ * @return blockTimestamp Third field from the COTI oracle row (same as pre-refactor behavior)
133
+ * @dev Pass the returned `cotiLastUpdated` and `tokenLastUpdated` verbatim into {deposit}/{withdraw} together
134
+ * with the same `tokenAmount` path; see {PrivacyBridge._validateOracleTimestamps} for strict equality UX.
135
+ */
136
+ function estimateDepositFee(uint256 tokenAmount) external view returns (uint256 fee, uint256 cotiLastUpdated, uint256 tokenLastUpdated, uint256 blockTimestamp) {
137
+ (fee, cotiLastUpdated, tokenLastUpdated, blockTimestamp) = _computeErc20FeeAndMeta(
138
+ tokenAmount,
139
+ depositFixedFee,
140
+ depositPercentageBps,
141
+ depositMaxFee,
142
+ tokenSymbol,
143
+ bridgedTokenDecimals
144
+ );
145
+ }
146
+
147
+ /**
148
+ * @notice Estimate the withdrawal fee in COTI for a given token amount
149
+ * @param tokenAmount The amount of ERC20 tokens to withdraw (raw units; very large values can revert in fee math)
150
+ * @return fee The estimated fee in native COTI (18 decimals)
151
+ * @return cotiLastUpdated COTI oracle data last update timestamp
152
+ * @return tokenLastUpdated Token oracle data last update timestamp
153
+ * @return blockTimestamp Third field from the COTI oracle row (same as pre-refactor behavior)
154
+ * @dev Same timestamp handoff as {estimateDepositFee}: use return values unchanged on the subsequent {withdraw}.
155
+ */
156
+ function estimateWithdrawFee(uint256 tokenAmount) external view returns (uint256 fee, uint256 cotiLastUpdated, uint256 tokenLastUpdated, uint256 blockTimestamp) {
157
+ (fee, cotiLastUpdated, tokenLastUpdated, blockTimestamp) = _computeErc20FeeAndMeta(
158
+ tokenAmount,
159
+ withdrawFixedFee,
160
+ withdrawPercentageBps,
161
+ withdrawMaxFee,
162
+ tokenSymbol,
163
+ bridgedTokenDecimals
164
+ );
165
+ }
166
+
167
+ /**
168
+ * @notice Collect the dynamic native COTI fee from msg.value and refund any excess
169
+ * @param fee The computed fee in native COTI
170
+ * @dev Reverts with {InsufficientCotiFee} if msg.value < fee.
171
+ * Excess above `fee` is sent back to `msg.sender` with a plain `call` (no receive hook guarantee).
172
+ * Smart wallets or contracts that revert or return false on unsolicited ETH will not receive the push;
173
+ * the excess is then credited to {refundableNativeExcess}[msg.sender] and emits `NativeRefundExcessPushFailed`
174
+ * (see {PrivacyBridge._creditRefundableNativeExcess} and {PrivacyBridge.claimRefundableNativeExcess}). Excess
175
+ * is never added to {accumulatedCotiFees}.
176
+ */
177
+ function _collectDynamicNativeFee(uint256 fee) internal {
178
+ if (msg.value < fee) revert InsufficientCotiFee();
179
+ // Verify contract balance covers the fee before accounting
180
+ if (address(this).balance < fee) revert InsufficientEthBalance();
181
+ accumulatedCotiFees += fee;
182
+ if (msg.value > fee) {
183
+ uint256 excess = msg.value - fee;
184
+ (bool ok, ) = msg.sender.call{value: excess}("");
185
+ if (!ok) {
186
+ _creditRefundableNativeExcess(msg.sender, excess);
187
+ }
188
+ }
189
+ }
190
+
191
+ /**
192
+ * @notice Initialize the PrivacyBridgeERC20 contract
193
+ * @param _token Address of the public ERC20 token (must be standard: no fee-on-transfer, no rebasing; same decimals as private token)
194
+ * @param _privateToken Address of the private token
195
+ * @param _tokenSymbol Band oracle symbol for the bridged token (e.g., "ETH", "WBTC") — required for Band Protocol compatibility check
196
+ * @param _priceOracle Non-zero price oracle (same requirement as {PrivacyBridge}'s constructor)
197
+ * @dev **Decimals:** reads `decimals()` on both tokens at deploy; reverts {DecimalsMismatch} if they differ—so
198
+ * mis-paired tokens fail **at construction**, not on first user tx. {bridgedTokenDecimals} is then cached
199
+ * immutably for fee math. After deploy, a mismatch cannot appear unless token contracts were misconfigured
200
+ * at deploy time or an upgradeable token later changes `decimals()` (exceptional external risk; not re-checked on-chain).
201
+ */
202
+ constructor(
203
+ address _token,
204
+ address _privateToken,
205
+ string memory _tokenSymbol,
206
+ address _feeRecipient,
207
+ address _rescueRecipient,
208
+ address _priceOracle
209
+ ) PrivacyBridge(_feeRecipient, _rescueRecipient, _priceOracle) {
210
+ if (_token == address(0)) revert InvalidTokenAddress();
211
+ if (_privateToken == address(0)) revert InvalidPrivateTokenAddress();
212
+
213
+ uint8 pubDecimals = IHasDecimals(_token).decimals();
214
+ if (pubDecimals != IHasDecimals(_privateToken).decimals()) revert DecimalsMismatch();
215
+ bridgedTokenDecimals = pubDecimals;
216
+
217
+ token = IERC20(_token);
218
+ privateToken = IPrivateERC20(_privateToken);
219
+ tokenSymbol = _tokenSymbol;
220
+ }
221
+
222
+ /**
223
+ * @notice Deposit public ERC20 tokens to receive equivalent private tokens
224
+ * @param amount Amount of public ERC20 tokens to deposit
225
+ * @param cotiOracleTimestamp COTI `lastUpdated` from the latest `estimateDepositFee` (must still equal on-chain at execution).
226
+ * @param tokenOracleTimestamp Token `lastUpdated` from the same estimate (must still equal on-chain at execution).
227
+ * @dev Native COTI fee: send msg.value >= computed fee. Excess native is push-refunded then pull-credited on failure
228
+ * ({_collectDynamicNativeFee}). If the Band row advances before inclusion, tx reverts with {OracleTimestampMismatch}—re-estimate and resubmit (see {_validateOracleTimestamps}).
229
+ */
230
+ function deposit(
231
+ uint256 amount,
232
+ uint256 cotiOracleTimestamp,
233
+ uint256 tokenOracleTimestamp
234
+ ) external payable nonReentrant whenNotPaused notBlacklisted {
235
+ _deposit(amount, cotiOracleTimestamp, tokenOracleTimestamp);
236
+ }
237
+
238
+ /**
239
+ * @dev Pulls public tokens before collecting the native COTI fee so a non-standard transfer
240
+ * (e.g. fee-on-transfer) reverts before debiting `msg.value`, and insufficient `msg.value`
241
+ * still reverts the whole tx including the token transfer.
242
+ */
243
+ function _deposit(uint256 amount, uint256 cotiOracleTimestamp, uint256 tokenOracleTimestamp) internal {
244
+ if (!isDepositEnabled) revert DepositDisabled();
245
+ if (amount == 0) revert AmountZero();
246
+ _checkDepositLimits(amount);
247
+ _validateOracleTimestamps(cotiOracleTimestamp, tokenOracleTimestamp, tokenSymbol);
248
+
249
+ uint256 fee = _computeErc20Fee(amount, depositFixedFee, depositPercentageBps, depositMaxFee);
250
+
251
+ uint256 balBefore = token.balanceOf(address(this));
252
+ token.safeTransferFrom(msg.sender, address(this), amount);
253
+ uint256 received = token.balanceOf(address(this)) - balBefore;
254
+ if (received != amount) revert UnexpectedTransferBalance(amount, received);
255
+
256
+ _collectDynamicNativeFee(fee);
257
+
258
+ totalUserLiability += received;
259
+ privateToken.mint(msg.sender, received);
260
+
261
+ emit Deposit(msg.sender, amount, received);
262
+ }
263
+
264
+ /**
265
+ * @notice Withdraw public ERC20 tokens by burning private tokens
266
+ * @param amount Amount of private tokens to burn
267
+ * @param cotiOracleTimestamp COTI `lastUpdated` from the latest `estimateWithdrawFee` (must still equal on-chain at execution).
268
+ * @param tokenOracleTimestamp Token `lastUpdated` from the same estimate (must still equal on-chain at execution).
269
+ * @dev Requires prior approval on the private token. Send `msg.value >= fee`; native fee is
270
+ * collected only after the public token transfer succeeds (mirrors {deposit} ordering). Oracle
271
+ * timestamp rules match {deposit} / {_validateOracleTimestamps}. Native excess handling matches {deposit}.
272
+ */
273
+ function withdraw(
274
+ uint256 amount,
275
+ uint256 cotiOracleTimestamp,
276
+ uint256 tokenOracleTimestamp
277
+ ) external payable nonReentrant whenNotPaused notBlacklisted {
278
+ _withdraw(amount, cotiOracleTimestamp, tokenOracleTimestamp);
279
+ }
280
+
281
+ /**
282
+ * @dev Mirrors {_deposit}: native fee is collected only after the ERC20 leg succeeds by standard
283
+ * semantics (here: burn + public transfer with full `userGain`). Insufficient `msg.value`
284
+ * then reverts the entire withdrawal including private burn and public transfer.
285
+ */
286
+ function _withdraw(uint256 amount, uint256 cotiOracleTimestamp, uint256 tokenOracleTimestamp) internal {
287
+ if (amount == 0) revert AmountZero();
288
+ _checkWithdrawLimits(amount);
289
+ _validateOracleTimestamps(cotiOracleTimestamp, tokenOracleTimestamp, tokenSymbol);
290
+
291
+ uint256 fee = _computeErc20Fee(amount, withdrawFixedFee, withdrawPercentageBps, withdrawMaxFee);
292
+
293
+ uint256 bridgeBalance = token.balanceOf(address(this));
294
+ if (bridgeBalance < amount) revert InsufficientBridgeLiquidity();
295
+
296
+ totalUserLiability -= amount;
297
+ privateToken.transferFrom(msg.sender, address(this), amount);
298
+ privateToken.burn(amount);
299
+
300
+ uint256 userBalBefore = token.balanceOf(msg.sender);
301
+ token.safeTransfer(msg.sender, amount);
302
+ uint256 userGain = token.balanceOf(msg.sender) - userBalBefore;
303
+ if (userGain != amount) revert UnexpectedTransferBalance(amount, userGain);
304
+
305
+ _collectDynamicNativeFee(fee);
306
+
307
+ emit Withdraw(msg.sender, amount, amount);
308
+ }
309
+
310
+ /**
311
+ * @notice Move ERC20 from this contract to {rescueRecipient} while the bridge is paused.
312
+ * @dev Requires {whenPaused} for every `_token` so rescue never runs concurrently with user flows.
313
+ * For the live public {token}, `amount` can be the full balance—including all TVL backing withdrawals.
314
+ * Same governance risk as {PrivacyBridgeCotiNative.rescueNative}: owner + pause can send user funds
315
+ * to {rescueRecipient}; see {PrivacyBridge} contract @dev (3). Private token cannot be rescued here
316
+ * ({CannotRescueBridgeToken}). {totalUserLiability} is intentionally **not** updated here: rescue only
317
+ * moves collateral to {rescueRecipient}; it does not burn private tokens or unwind user obligations on
318
+ * this ledger, so outstanding claims can exceed {token} held by this contract until a separate migration
319
+ * path makes users whole.
320
+ */
321
+ function rescueERC20(
322
+ address _token,
323
+ uint256 amount
324
+ ) external onlyOwner nonReentrant whenPaused {
325
+ if (amount == 0) revert AmountZero();
326
+
327
+ if (_token == address(privateToken)) revert CannotRescueBridgeToken();
328
+
329
+ IERC20(_token).safeTransfer(rescueRecipient, amount);
330
+
331
+ emit ERC20Rescued(_token, rescueRecipient, amount);
332
+ }
333
+ }
@@ -0,0 +1,22 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.19;
3
+
4
+ import "./PrivacyBridgeERC20.sol";
5
+ import "../token/PrivateERC20/tokens/PrivateBridgedUSDC.sol";
6
+
7
+ /**
8
+ * @title PrivacyBridgeUSDCe
9
+ * @notice Bridge contract for converting between USDC.e and privacy-preserving p.USDC.e tokens
10
+ */
11
+ contract PrivacyBridgeUSDCe is PrivacyBridgeERC20 {
12
+
13
+ constructor(
14
+ address _usdc,
15
+ address _privateUsdc,
16
+ address _feeRecipient,
17
+ address _rescueRecipient,
18
+ address _priceOracle
19
+ ) PrivacyBridgeERC20(_usdc, _privateUsdc, "USDC", _feeRecipient, _rescueRecipient, _priceOracle) {
20
+
21
+ }
22
+ }