@coti-io/coti-contracts 1.0.9 → 1.2.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 (271) hide show
  1. package/.github/workflows/npm-publish.yml +18 -14
  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/mocks/token/ERC20Mock.sol +19 -0
  9. package/contracts/mocks/token/PrivateERC20/EncryptedTokenReceiverMock.sol +18 -0
  10. package/contracts/mocks/token/PrivateERC20/PrivacyBridgeERC20Mock.sol +13 -0
  11. package/contracts/mocks/token/PrivateERC20/PrivateERC20AuditorSupplyMock.sol +44 -0
  12. package/contracts/mocks/token/PrivateERC20/PrivateERC20CappedMock.sol +23 -0
  13. package/contracts/mocks/token/PrivateERC20/PrivateERC20GtCallerMock.sol +29 -0
  14. package/contracts/mocks/token/PrivateERC20/PrivateERC20Mock.sol +9 -4
  15. package/contracts/mocks/token/PrivateERC20/PrivateERC20ReentrantReceiverMock.sol +39 -0
  16. package/contracts/mocks/token/PrivateERC20/PublicReentrantTokenReceiverMock.sol +29 -0
  17. package/contracts/mocks/token/PrivateERC20/PublicTokenReceiverBoolMock.sol +18 -0
  18. package/contracts/mocks/token/PrivateERC20/PublicTokenReceiverMock.sol +12 -0
  19. package/contracts/mocks/utils/mpc/Arithmetic128TestsContract.sol +123 -0
  20. package/contracts/mocks/utils/mpc/Arithmetic256TestsContract.sol +122 -0
  21. package/contracts/mocks/utils/mpc/Bitwise128TestsContract.sol +65 -0
  22. package/contracts/mocks/utils/mpc/Bitwise256TestsContract.sol +65 -0
  23. package/contracts/mocks/utils/mpc/CheckedArithmetic128WithOverflowBitTestsContract.sol +64 -0
  24. package/contracts/mocks/utils/mpc/CheckedArithmetic256WithOverflowBitTestsContract.sol +64 -0
  25. package/contracts/mocks/utils/mpc/Comparison128TestsContract.sol +98 -0
  26. package/contracts/mocks/utils/mpc/Comparison256TestsContract.sol +98 -0
  27. package/contracts/mocks/utils/mpc/MinMax128TestsContract.sol +44 -0
  28. package/contracts/mocks/utils/mpc/MinMax256TestsContract.sol +44 -0
  29. package/contracts/mocks/utils/mpc/MinimalImplementation.sol +55 -0
  30. package/contracts/mocks/utils/mpc/MinimalProxy.sol +27 -0
  31. package/contracts/mocks/utils/mpc/MpcOperations128TestContract.sol +267 -0
  32. package/contracts/mocks/utils/mpc/MpcOperationsTestContract.sol +334 -0
  33. package/contracts/mocks/utils/mpc/Mux128TestsContract.sol +24 -0
  34. package/contracts/mocks/utils/mpc/Mux256TestsContract.sol +24 -0
  35. package/contracts/mocks/utils/mpc/OnBoard128TestsContract.sol +93 -0
  36. package/contracts/mocks/utils/mpc/OnBoard256TestsContract.sol +116 -0
  37. package/contracts/mocks/utils/mpc/PrivacyImplementationV1.sol +157 -0
  38. package/contracts/mocks/utils/mpc/PrivacyImplementationV2.sol +133 -0
  39. package/contracts/mocks/utils/mpc/PrivacyProxy.sol +137 -0
  40. package/contracts/mocks/utils/mpc/Random128TestsContract.sol +32 -0
  41. package/contracts/mocks/utils/mpc/Random256TestsContract.sol +32 -0
  42. package/contracts/mocks/utils/mpc/Shift128TestsContract.sol +36 -0
  43. package/contracts/mocks/utils/mpc/Shift256TestsContract.sol +36 -0
  44. package/contracts/mocks/utils/mpc/Transfer128TestsContract.sol +29 -0
  45. package/contracts/mocks/utils/mpc/Transfer256TestsContract.sol +29 -0
  46. package/contracts/mocks/utils/mpc/TransferWithAllowance128TestsContract.sol +32 -0
  47. package/contracts/mocks/utils/mpc/TransferWithAllowance256TestsContract.sol +32 -0
  48. package/contracts/mocks/utils/mpc/ValidateCiphertext128TestsContract.sol +59 -0
  49. package/contracts/mocks/utils/mpc/ValidateCiphertext256TestsContract.sol +63 -0
  50. package/contracts/mocks/utils/mpc/ValidateCiphertextTestsContract.sol +99 -0
  51. package/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock.sol +7 -6
  52. package/contracts/node/CotiNodeRewards.sol +199 -0
  53. package/contracts/node/SoulboundNodeNFT.sol +519 -0
  54. package/contracts/privacyBridge/PrivacyBridge.sol +318 -0
  55. package/contracts/privacyBridge/PrivacyBridgeCotiNative.sol +268 -0
  56. package/contracts/privacyBridge/PrivacyBridgeERC20.sol +251 -0
  57. package/contracts/privacyBridge/PrivacyBridgeUSDCe.sol +16 -0
  58. package/contracts/privacyBridge/PrivacyBridgeUSDT.sol +17 -0
  59. package/contracts/privacyBridge/PrivacyBridgeWADA.sol +17 -0
  60. package/contracts/privacyBridge/PrivacyBridgeWBTC.sol +17 -0
  61. package/contracts/privacyBridge/PrivacyBridgeWETH.sol +17 -0
  62. package/contracts/privacyBridge/PrivacyBridgegCoti.sol +17 -0
  63. package/contracts/token/PrivateERC20/IPrivateERC20.sol +273 -40
  64. package/contracts/token/PrivateERC20/ITokenReceiver.sol +17 -0
  65. package/contracts/token/PrivateERC20/ITokenReceiverEncrypted.sol +20 -0
  66. package/contracts/token/PrivateERC20/PrivateERC20.sol +861 -152
  67. package/contracts/token/PrivateERC20/tokens/PrivateBridgedUSDC.sol +17 -0
  68. package/contracts/token/PrivateERC20/tokens/PrivateCOTI.sol +13 -0
  69. package/contracts/token/PrivateERC20/tokens/PrivateCOTITreasuryGovernanceToken.sol +17 -0
  70. package/contracts/token/PrivateERC20/tokens/PrivateTetherUSD.sol +17 -0
  71. package/contracts/token/PrivateERC20/tokens/PrivateWrappedADA.sol +17 -0
  72. package/contracts/token/PrivateERC20/tokens/PrivateWrappedBTC.sol +17 -0
  73. package/contracts/token/PrivateERC20/tokens/PrivateWrappedEther.sol +13 -0
  74. package/contracts/utils/mpc/MpcCore.sol +10891 -2449
  75. package/contracts/utils/mpc/MpcInterface.sol +7 -2
  76. package/hardhat/gasPriceBump.ts +60 -0
  77. package/hardhat.config.ts +60 -12
  78. package/package.json +21 -3
  79. package/scripts/deploySoulboundNodeNFT.ts +57 -0
  80. package/test/token/PrivateERC20/PrivacyBridge.fees.test.ts +327 -0
  81. package/test/token/PrivateERC20/PrivateERC20.test.ts +1109 -268
  82. package/test/utils/mpc/Bitwise128.test.ts +92 -0
  83. package/test/utils/mpc/Bitwise256.test.ts +101 -0
  84. package/test/utils/mpc/BuildInputText128.test.ts +398 -0
  85. package/test/utils/mpc/CheckedArithmetic128.test.ts +45 -0
  86. package/test/utils/mpc/CheckedArithmetic256.test.ts +45 -0
  87. package/test/utils/mpc/Comparison128.test.ts +48 -0
  88. package/test/utils/mpc/Comparison256.test.ts +48 -0
  89. package/test/utils/mpc/InvalidCiphertext.test.ts +179 -0
  90. package/test/utils/mpc/InvalidCiphertext128.test.ts +179 -0
  91. package/test/utils/mpc/InvalidCiphertext256.test.ts +201 -0
  92. package/test/utils/mpc/InvalidTransfer128.test.ts +166 -0
  93. package/test/utils/mpc/InvalidTransfer256.test.ts +158 -0
  94. package/test/utils/mpc/MinMax128.test.ts +44 -0
  95. package/test/utils/mpc/MinMax256.test.ts +44 -0
  96. package/test/utils/mpc/MinimalProxyDemo.test.ts +280 -0
  97. package/test/utils/mpc/MpcOperations.test.ts +589 -0
  98. package/test/utils/mpc/MpcOperations128.test.ts +632 -0
  99. package/test/utils/mpc/Mux128.test.ts +41 -0
  100. package/test/utils/mpc/Mux256.test.ts +41 -0
  101. package/test/utils/mpc/NegativeCases.test.ts +478 -0
  102. package/test/utils/mpc/NegativeCases128.test.ts +237 -0
  103. package/test/utils/mpc/NegativeCases256.test.ts +236 -0
  104. package/test/utils/mpc/OnBoard128.test.ts +90 -0
  105. package/test/utils/mpc/OnBoard256.test.ts +114 -0
  106. package/test/utils/mpc/Precompile128.test.ts +51 -0
  107. package/test/utils/mpc/Precompile256.test.ts +115 -0
  108. package/test/utils/mpc/ProxyValidation.test.ts +199 -0
  109. package/test/utils/mpc/Random128.test.ts +47 -0
  110. package/test/utils/mpc/Random256.test.ts +47 -0
  111. package/test/utils/mpc/Shift128.test.ts +41 -0
  112. package/test/utils/mpc/Shift256.test.ts +41 -0
  113. package/test/utils/mpc/Transfer128.test.ts +46 -0
  114. package/test/utils/mpc/Transfer256.test.ts +46 -0
  115. package/test/utils/mpc/TransferWithAllowance128.test.ts +48 -0
  116. package/test/utils/mpc/TransferWithAllowance256.test.ts +48 -0
  117. package/test/utils/mpc/UpgradeablePrivacyProxy.test.ts +307 -0
  118. package/test/utils/mpc/ValidateCiphertext.test.ts +221 -0
  119. package/test/utils/mpc/ValidateCiphertext256.test.ts +161 -0
  120. package/test/utils/mpc/ValidateCiphertext256Decryption.test.ts +383 -0
  121. package/test/utils/mpc/WalletEncryptionFailures.test.ts +494 -0
  122. package/test/utils/privateErc20Helpers.ts +97 -0
  123. package/typechain-types/@openzeppelin/contracts/access/Ownable.ts +153 -0
  124. package/typechain-types/@openzeppelin/contracts/access/index.ts +4 -0
  125. package/typechain-types/@openzeppelin/contracts/index.ts +2 -0
  126. package/typechain-types/@openzeppelin/contracts/token/ERC20/IERC20.ts +262 -0
  127. package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.ts +143 -0
  128. package/typechain-types/@openzeppelin/contracts/token/ERC20/extensions/index.ts +4 -0
  129. package/typechain-types/@openzeppelin/contracts/token/ERC20/index.ts +6 -0
  130. package/typechain-types/@openzeppelin/contracts/token/index.ts +2 -0
  131. package/typechain-types/contracts/disperse/coinByRatio/FixedRatioCoinDisperser.ts +679 -0
  132. package/typechain-types/contracts/disperse/coinByRatio/index.ts +4 -0
  133. package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/IMintableERC20.ts +97 -0
  134. package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/MintDisperser.ts +206 -0
  135. package/typechain-types/contracts/disperse/disperseToken/MintDisperser.sol/index.ts +5 -0
  136. package/typechain-types/contracts/disperse/disperseToken/TokenDisperser.ts +191 -0
  137. package/typechain-types/contracts/disperse/disperseToken/index.ts +6 -0
  138. package/typechain-types/contracts/disperse/index.ts +7 -0
  139. package/typechain-types/contracts/index.ts +2 -0
  140. package/typechain-types/contracts/mocks/token/PrivateERC20/PrivateERC20Mock.ts +77 -60
  141. package/typechain-types/contracts/mocks/utils/mpc/Arithmetic128BitTestsContract.ts +341 -0
  142. package/typechain-types/contracts/mocks/utils/mpc/Arithmetic128TestsContract.ts +311 -0
  143. package/typechain-types/contracts/mocks/utils/mpc/Arithmetic256BitTestsContract.ts +347 -0
  144. package/typechain-types/contracts/mocks/utils/mpc/Arithmetic256TestsContract.ts +311 -0
  145. package/typechain-types/contracts/mocks/utils/mpc/Bitwise128BitTestsContract.ts +186 -0
  146. package/typechain-types/contracts/mocks/utils/mpc/Bitwise128TestsContract.ts +179 -0
  147. package/typechain-types/contracts/mocks/utils/mpc/Bitwise256BitTestsContract.ts +186 -0
  148. package/typechain-types/contracts/mocks/utils/mpc/Bitwise256TestsContract.ts +179 -0
  149. package/typechain-types/contracts/mocks/utils/mpc/CheckedArithmetic128WithOverflowBitTestsContract.ts +206 -0
  150. package/typechain-types/contracts/mocks/utils/mpc/CheckedArithmetic256WithOverflowBitTestsContract.ts +206 -0
  151. package/typechain-types/contracts/mocks/utils/mpc/Comparison128BitTestsContract.ts +260 -0
  152. package/typechain-types/contracts/mocks/utils/mpc/Comparison128TestsContract.ts +278 -0
  153. package/typechain-types/contracts/mocks/utils/mpc/Comparison256BitTestsContract.ts +260 -0
  154. package/typechain-types/contracts/mocks/utils/mpc/Comparison256TestsContract.ts +278 -0
  155. package/typechain-types/contracts/mocks/utils/mpc/MinMax128TestsContract.ts +142 -0
  156. package/typechain-types/contracts/mocks/utils/mpc/MinMax256TestsContract.ts +142 -0
  157. package/typechain-types/contracts/mocks/utils/mpc/MinimalImplementation.ts +259 -0
  158. package/typechain-types/contracts/mocks/utils/mpc/MinimalProxy.ts +90 -0
  159. package/typechain-types/contracts/mocks/utils/mpc/Miscellaneous128BitTestsContract.ts +302 -0
  160. package/typechain-types/contracts/mocks/utils/mpc/Miscellaneous256BitTestsContract.ts +322 -0
  161. package/typechain-types/contracts/mocks/utils/mpc/MpcOperations128TestContract.ts +388 -0
  162. package/typechain-types/contracts/mocks/utils/mpc/MpcOperationsTestContract.ts +455 -0
  163. package/typechain-types/contracts/mocks/utils/mpc/Mux128TestsContract.ts +109 -0
  164. package/typechain-types/contracts/mocks/utils/mpc/Mux256TestsContract.ts +109 -0
  165. package/typechain-types/contracts/mocks/utils/mpc/OnBoard128TestsContract.ts +166 -0
  166. package/typechain-types/contracts/mocks/utils/mpc/OnBoard256TestsContract.ts +194 -0
  167. package/typechain-types/contracts/mocks/utils/mpc/PrivacyImplementationV1.ts +385 -0
  168. package/typechain-types/contracts/mocks/utils/mpc/PrivacyImplementationV2.ts +441 -0
  169. package/typechain-types/contracts/mocks/utils/mpc/PrivacyProxy.ts +201 -0
  170. package/typechain-types/contracts/mocks/utils/mpc/Random128TestsContract.ts +131 -0
  171. package/typechain-types/contracts/mocks/utils/mpc/Random256TestsContract.ts +131 -0
  172. package/typechain-types/contracts/mocks/utils/mpc/Shift128TestsContract.ts +142 -0
  173. package/typechain-types/contracts/mocks/utils/mpc/Shift256TestsContract.ts +142 -0
  174. package/typechain-types/contracts/mocks/utils/mpc/Transfer128TestsContract.ts +109 -0
  175. package/typechain-types/contracts/mocks/utils/mpc/Transfer256TestsContract.ts +109 -0
  176. package/typechain-types/contracts/mocks/utils/mpc/TransferWithAllowance128TestsContract.ts +128 -0
  177. package/typechain-types/contracts/mocks/utils/mpc/TransferWithAllowance256TestsContract.ts +128 -0
  178. package/typechain-types/contracts/mocks/utils/mpc/ValidateCiphertext128TestsContract.ts +198 -0
  179. package/typechain-types/contracts/mocks/utils/mpc/ValidateCiphertext256TestsContract.ts +182 -0
  180. package/typechain-types/contracts/mocks/utils/mpc/ValidateCiphertextTestsContract.ts +257 -0
  181. package/typechain-types/contracts/mocks/utils/mpc/index.ts +32 -0
  182. package/typechain-types/contracts/token/PrivateERC20/IPrivateERC20.ts +77 -60
  183. package/typechain-types/contracts/token/PrivateERC20/PrivateERC20.ts +77 -60
  184. package/typechain-types/contracts/utils/mpc/MpcInterface.sol/ExtendedOperations.ts +111 -10
  185. package/typechain-types/factories/@openzeppelin/contracts/access/Ownable__factory.ts +74 -0
  186. package/typechain-types/factories/@openzeppelin/contracts/access/index.ts +4 -0
  187. package/typechain-types/factories/@openzeppelin/contracts/index.ts +1 -0
  188. package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/IERC20__factory.ts +205 -0
  189. package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit__factory.ts +100 -0
  190. package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/extensions/index.ts +4 -0
  191. package/typechain-types/factories/@openzeppelin/contracts/token/ERC20/index.ts +5 -0
  192. package/typechain-types/factories/@openzeppelin/contracts/token/index.ts +1 -0
  193. package/typechain-types/factories/contracts/disperse/coinByRatio/FixedRatioCoinDisperser__factory.ts +759 -0
  194. package/typechain-types/factories/contracts/disperse/coinByRatio/index.ts +4 -0
  195. package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/IMintableERC20__factory.ts +43 -0
  196. package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/MintDisperser__factory.ts +185 -0
  197. package/typechain-types/factories/contracts/disperse/disperseToken/MintDisperser.sol/index.ts +5 -0
  198. package/typechain-types/factories/contracts/disperse/disperseToken/TokenDisperser__factory.ts +198 -0
  199. package/typechain-types/factories/contracts/disperse/disperseToken/index.ts +5 -0
  200. package/typechain-types/factories/contracts/disperse/index.ts +5 -0
  201. package/typechain-types/factories/contracts/index.ts +1 -0
  202. package/typechain-types/factories/contracts/mocks/access/DataPrivacyFramework/DataPrivacyFrameworkMock__factory.ts +1 -1
  203. package/typechain-types/factories/contracts/mocks/token/PrivateERC20/PrivateERC20Mock__factory.ts +179 -47
  204. package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic128BitTestsContract__factory.ts +349 -0
  205. package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic128TestsContract__factory.ts +330 -0
  206. package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic256BitTestsContract__factory.ts +364 -0
  207. package/typechain-types/factories/contracts/mocks/utils/mpc/Arithmetic256TestsContract__factory.ts +330 -0
  208. package/typechain-types/factories/contracts/mocks/utils/mpc/ArithmeticTestsContract__factory.ts +1 -1
  209. package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise128BitTestsContract__factory.ts +182 -0
  210. package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise128TestsContract__factory.ts +184 -0
  211. package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise256BitTestsContract__factory.ts +182 -0
  212. package/typechain-types/factories/contracts/mocks/utils/mpc/Bitwise256TestsContract__factory.ts +184 -0
  213. package/typechain-types/factories/contracts/mocks/utils/mpc/BitwiseTestsContract__factory.ts +1 -1
  214. package/typechain-types/factories/contracts/mocks/utils/mpc/CheckedArithmetic128WithOverflowBitTestsContract__factory.ts +203 -0
  215. package/typechain-types/factories/contracts/mocks/utils/mpc/CheckedArithmetic256WithOverflowBitTestsContract__factory.ts +203 -0
  216. package/typechain-types/factories/contracts/mocks/utils/mpc/CheckedArithmeticWIthOverflowBitTestsContract.sol/CheckedArithmeticWithOverflowBitTestsContract__factory.ts +1 -1
  217. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison128BitTestsContract__factory.ts +255 -0
  218. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison128TestsContract__factory.ts +295 -0
  219. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison1TestsContract__factory.ts +1 -1
  220. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison256BitTestsContract__factory.ts +255 -0
  221. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison256TestsContract__factory.ts +295 -0
  222. package/typechain-types/factories/contracts/mocks/utils/mpc/Comparison2TestsContract__factory.ts +1 -1
  223. package/typechain-types/factories/contracts/mocks/utils/mpc/MinMax128TestsContract__factory.ts +147 -0
  224. package/typechain-types/factories/contracts/mocks/utils/mpc/MinMax256TestsContract__factory.ts +147 -0
  225. package/typechain-types/factories/contracts/mocks/utils/mpc/MinMaxTestsContract__factory.ts +1 -1
  226. package/typechain-types/factories/contracts/mocks/utils/mpc/MinimalImplementation__factory.ts +263 -0
  227. package/typechain-types/factories/contracts/mocks/utils/mpc/MinimalProxy__factory.ts +104 -0
  228. package/typechain-types/factories/contracts/mocks/utils/mpc/Miscellaneous128BitTestsContract__factory.ts +332 -0
  229. package/typechain-types/factories/contracts/mocks/utils/mpc/Miscellaneous1TestsContract__factory.ts +1 -1
  230. package/typechain-types/factories/contracts/mocks/utils/mpc/Miscellaneous256BitTestsContract__factory.ts +380 -0
  231. package/typechain-types/factories/contracts/mocks/utils/mpc/MiscellaneousTestsContract__factory.ts +1 -1
  232. package/typechain-types/factories/contracts/mocks/utils/mpc/MpcOperations128TestContract__factory.ts +723 -0
  233. package/typechain-types/factories/contracts/mocks/utils/mpc/MpcOperationsTestContract__factory.ts +1410 -0
  234. package/typechain-types/factories/contracts/mocks/utils/mpc/Mux128TestsContract__factory.ts +115 -0
  235. package/typechain-types/factories/contracts/mocks/utils/mpc/Mux256TestsContract__factory.ts +115 -0
  236. package/typechain-types/factories/contracts/mocks/utils/mpc/OffboardToUserKeyTestContract__factory.ts +1 -1
  237. package/typechain-types/factories/contracts/mocks/utils/mpc/OnBoard128TestsContract__factory.ts +175 -0
  238. package/typechain-types/factories/contracts/mocks/utils/mpc/OnBoard256TestsContract__factory.ts +205 -0
  239. package/typechain-types/factories/contracts/mocks/utils/mpc/PrivacyImplementationV1__factory.ts +521 -0
  240. package/typechain-types/factories/contracts/mocks/utils/mpc/PrivacyImplementationV2__factory.ts +648 -0
  241. package/typechain-types/factories/contracts/mocks/utils/mpc/PrivacyProxy__factory.ts +179 -0
  242. package/typechain-types/factories/contracts/mocks/utils/mpc/Random128TestsContract__factory.ts +131 -0
  243. package/typechain-types/factories/contracts/mocks/utils/mpc/Random256TestsContract__factory.ts +131 -0
  244. package/typechain-types/factories/contracts/mocks/utils/mpc/Shift128TestsContract__factory.ts +147 -0
  245. package/typechain-types/factories/contracts/mocks/utils/mpc/Shift256TestsContract__factory.ts +147 -0
  246. package/typechain-types/factories/contracts/mocks/utils/mpc/ShiftTestsContract__factory.ts +1 -1
  247. package/typechain-types/factories/contracts/mocks/utils/mpc/StringTestsContract__factory.ts +1 -1
  248. package/typechain-types/factories/contracts/mocks/utils/mpc/Transfer128TestsContract__factory.ts +135 -0
  249. package/typechain-types/factories/contracts/mocks/utils/mpc/Transfer256TestsContract__factory.ts +135 -0
  250. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferScalarTestsContract__factory.ts +1 -1
  251. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferTestsContract__factory.ts +1 -1
  252. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance128TestsContract__factory.ts +154 -0
  253. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance256TestsContract__factory.ts +154 -0
  254. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_16TestsContract__factory.ts +1 -1
  255. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_32TestsContract__factory.ts +1 -1
  256. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_64TestsContract__factory.ts +1 -1
  257. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowance64_8TestsContract__factory.ts +1 -1
  258. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowanceScalarTestsContract__factory.ts +1 -1
  259. package/typechain-types/factories/contracts/mocks/utils/mpc/TransferWithAllowanceTestsContract__factory.ts +1 -1
  260. package/typechain-types/factories/contracts/mocks/utils/mpc/ValidateCiphertext128TestsContract__factory.ts +190 -0
  261. package/typechain-types/factories/contracts/mocks/utils/mpc/ValidateCiphertext256TestsContract__factory.ts +210 -0
  262. package/typechain-types/factories/contracts/mocks/utils/mpc/ValidateCiphertextTestsContract__factory.ts +260 -0
  263. package/typechain-types/factories/contracts/mocks/utils/mpc/index.ts +32 -0
  264. package/typechain-types/factories/contracts/mocks/wallet/PrivateERC20Wallet/PrivateERC20WalletMock__factory.ts +7 -7
  265. package/typechain-types/factories/contracts/token/PrivateERC20/IPrivateERC20__factory.ts +174 -42
  266. package/typechain-types/factories/contracts/token/PrivateERC20/PrivateERC20__factory.ts +174 -42
  267. package/typechain-types/factories/contracts/utils/mpc/MpcInterface.sol/ExtendedOperations__factory.ts +126 -0
  268. package/typechain-types/hardhat.d.ts +702 -0
  269. package/typechain-types/index.ts +78 -0
  270. package/contracts/mocks/utils/mpc/README.md +0 -486
  271. package/contracts/package.json +0 -11
@@ -0,0 +1,519 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
5
+ import "@openzeppelin/contracts/access/Ownable.sol";
6
+ import "@openzeppelin/contracts/utils/Strings.sol";
7
+ import "@openzeppelin/contracts/utils/Base64.sol";
8
+
9
+ /**
10
+ * @title SoulboundNodeNFT
11
+ * @notice ERC-721 Soulbound Node Identity NFT with ERC-5192 support
12
+ *
13
+ * @dev High-level properties:
14
+ * - Non-transferable (Soulbound)
15
+ * - ERC-5192 compliant (locked NFTs)
16
+ * - Only contract owner can mint
17
+ * - One NFT per wallet enforced
18
+ * - Minting can be paused by owner
19
+ * - Unlimited total supply
20
+ * - Burnable by token owner or contract owner
21
+ * - On-chain base64-encoded JSON metadata
22
+ * - Uses custom Solidity errors (gas efficient)
23
+ *
24
+ * @dev Intended use case:
25
+ * - Node / validator identity
26
+ * - Credentials
27
+ * - Non-transferable attestations
28
+ */
29
+
30
+ /// -----------------------------------------------------------------------
31
+ /// ERC-5192: Minimal Soulbound NFTs
32
+ /// -----------------------------------------------------------------------
33
+
34
+ /**
35
+ * @dev ERC-5192 interface for signaling soulbound (non-transferable) NFTs.
36
+ * See: https://eips.ethereum.org/EIPS/eip-5192
37
+ */
38
+ interface IERC5192 {
39
+ /// @notice Emitted when a token is locked (becomes soulbound)
40
+ event Locked(uint256 tokenId);
41
+
42
+ /// @notice Returns whether a token is locked (non-transferable)
43
+ function locked(uint256 tokenId) external view returns (bool);
44
+ }
45
+
46
+ /// -----------------------------------------------------------------------
47
+ /// Custom errors (cheaper than revert strings)
48
+ /// -----------------------------------------------------------------------
49
+
50
+ error InvalidRecipient();
51
+ error AlreadyOwnsNodeNFT();
52
+ error NodeNameRequired();
53
+ error NodeNameTooLong();
54
+ error SocialURLTooLong();
55
+ error NonexistentToken();
56
+ error SoulboundOperation();
57
+ error NotAuthorized();
58
+ error MintPaused();
59
+
60
+ /// -----------------------------------------------------------------------
61
+ /// Main contract
62
+ /// -----------------------------------------------------------------------
63
+
64
+ contract SoulboundNodeNFT is ERC721, Ownable, IERC5192 {
65
+ using Strings for uint256;
66
+
67
+ /// @notice Last minted token ID (starts at 0, first mint = 1)
68
+ uint256 public nextTokenId;
69
+
70
+ /// @notice Maximum length (in bytes) for nodeName and socialURL
71
+ uint256 public constant MAX_TEXT_BYTES = 150;
72
+
73
+ /**
74
+ * @notice If true, minting is paused.
75
+ * @dev Burn operations are NOT affected.
76
+ */
77
+ bool public mintPaused;
78
+
79
+ /// @notice Node-specific metadata stored on-chain
80
+ struct NodeData {
81
+ string nodeName; // required
82
+ string nodeImageURI; // optional (ipfs:// or https://)
83
+ string socialURL; // optional
84
+ bool isHot; // true = hot node, false = cold node
85
+ }
86
+
87
+ /// @dev tokenId => NodeData
88
+ mapping(uint256 => NodeData) private _nodeData;
89
+
90
+ /// @notice Emitted when a new node NFT is minted
91
+ event NodeMinted(
92
+ address indexed to,
93
+ uint256 indexed tokenId,
94
+ string nodeName,
95
+ string nodeImageURI,
96
+ string socialURL
97
+ );
98
+
99
+ /// @notice Emitted when mint pause state is changed
100
+ event MintPausedSet(bool paused);
101
+
102
+ /// @notice Emitted when a token's image URI is updated
103
+ event ImageURIUpdated(uint256 indexed tokenId, string newImageURI);
104
+
105
+ /// @notice Emitted when a token's social URL is updated
106
+ event SocialURLUpdated(uint256 indexed tokenId, string newSocialURL);
107
+
108
+ /// @notice Emitted when a token's node name is updated
109
+ event NodeNameUpdated(uint256 indexed tokenId, string newNodeName);
110
+
111
+ /// @notice Emitted when a token's hot/cold status is updated
112
+ event NodeHotStatusUpdated(uint256 indexed tokenId, bool isHot);
113
+
114
+ /**
115
+ * @notice Contract constructor
116
+ * @param name_ ERC-721 collection name
117
+ * @param symbol_ ERC-721 collection symbol
118
+ * @param initialOwner Address that becomes contract owner
119
+ */
120
+ constructor(
121
+ string memory name_,
122
+ string memory symbol_,
123
+ address initialOwner
124
+ ) ERC721(name_, symbol_) {
125
+ _transferOwnership(initialOwner);
126
+ mintPaused = false;
127
+ }
128
+
129
+ /// -----------------------------------------------------------------------
130
+ /// Admin: pause / unpause minting
131
+ /// -----------------------------------------------------------------------
132
+
133
+ /**
134
+ * @notice Pause minting operations
135
+ * @dev Only the contract owner can call this function
136
+ * @dev Only affects minting, not burning operations
137
+ * @dev Emits MintPausedSet event with true
138
+ */
139
+ function pauseMint() external onlyOwner {
140
+ mintPaused = true;
141
+ emit MintPausedSet(true);
142
+ }
143
+
144
+ /**
145
+ * @notice Unpause minting operations
146
+ * @dev Only the contract owner can call this function
147
+ * @dev Emits MintPausedSet event with false
148
+ */
149
+ function unpauseMint() external onlyOwner {
150
+ mintPaused = false;
151
+ emit MintPausedSet(false);
152
+ }
153
+
154
+ /// -----------------------------------------------------------------------
155
+ /// ERC-5192 (Soulbound signaling)
156
+ /// -----------------------------------------------------------------------
157
+
158
+ /**
159
+ * @notice Check whether a token is locked (soulbound)
160
+ * @param tokenId Token ID to check
161
+ * @return Always true for existing tokens
162
+ * @dev Reverts if token does not exist
163
+ */
164
+ function locked(uint256 tokenId) external view override returns (bool) {
165
+ if (_ownerOf(tokenId) == address(0)) revert NonexistentToken();
166
+ return true;
167
+ }
168
+
169
+ /**
170
+ * @notice ERC-165 interface support
171
+ * @param interfaceId Interface identifier to check
172
+ * @return true if the contract supports the interface, false otherwise
173
+ * @dev Supports ERC721, ERC165, and ERC5192 interfaces
174
+ */
175
+ function supportsInterface(
176
+ bytes4 interfaceId
177
+ ) public view override(ERC721) returns (bool) {
178
+ return
179
+ interfaceId == type(IERC5192).interfaceId ||
180
+ super.supportsInterface(interfaceId);
181
+ }
182
+
183
+ /// -----------------------------------------------------------------------
184
+ /// Minting (ONLY OWNER)
185
+ /// -----------------------------------------------------------------------
186
+
187
+ /**
188
+ * @notice Mint a new soulbound Node NFT
189
+ * @param to Recipient address
190
+ * @param nodeName Node name (required, <=150 bytes)
191
+ * @param nodeImageURI Optional image URI
192
+ * @param socialURL Optional social URL (<=150 bytes)
193
+ * @return tokenId The ID of the newly minted token
194
+ * @dev Restrictions:
195
+ * - Only contract owner can mint
196
+ * - Minting must not be paused
197
+ * - Recipient may own at most one NFT
198
+ * @dev Reverts if:
199
+ * - Minting is paused (MintPaused)
200
+ * - to is the zero address (InvalidRecipient)
201
+ * - to already owns an NFT (AlreadyOwnsNodeNFT)
202
+ * - nodeName is empty (NodeNameRequired)
203
+ * - nodeName exceeds MAX_TEXT_BYTES (NodeNameTooLong)
204
+ * - socialURL exceeds MAX_TEXT_BYTES (SocialURLTooLong)
205
+ * @dev Emits Locked and NodeMinted events
206
+ */
207
+ function mintNode(
208
+ address to,
209
+ string calldata nodeName,
210
+ string calldata nodeImageURI,
211
+ string calldata socialURL
212
+ ) external onlyOwner returns (uint256 tokenId) {
213
+ if (mintPaused) revert MintPaused();
214
+ if (to == address(0)) revert InvalidRecipient();
215
+ if (balanceOf(to) != 0) revert AlreadyOwnsNodeNFT();
216
+ if (bytes(nodeName).length == 0) revert NodeNameRequired();
217
+ if (bytes(nodeName).length > MAX_TEXT_BYTES) revert NodeNameTooLong();
218
+ if (bytes(socialURL).length > MAX_TEXT_BYTES) revert SocialURLTooLong();
219
+
220
+ tokenId = ++nextTokenId;
221
+
222
+ _safeMint(to, tokenId);
223
+
224
+ _nodeData[tokenId] = NodeData({
225
+ nodeName: nodeName,
226
+ nodeImageURI: nodeImageURI,
227
+ socialURL: socialURL,
228
+ // Default new nodes to hot; can be updated later via setNodeHotStatus
229
+ isHot: true
230
+ });
231
+
232
+ emit Locked(tokenId);
233
+ emit NodeMinted(to, tokenId, nodeName, nodeImageURI, socialURL);
234
+ }
235
+
236
+ /**
237
+ * @notice Get node metadata for a token
238
+ * @param tokenId Token ID to query
239
+ * @return NodeData struct containing nodeName, nodeImageURI, and socialURL
240
+ * @dev Reverts if the token does not exist (NonexistentToken)
241
+ */
242
+ function nodeData(uint256 tokenId) external view returns (NodeData memory) {
243
+ if (_ownerOf(tokenId) == address(0)) revert NonexistentToken();
244
+ return _nodeData[tokenId];
245
+ }
246
+
247
+ /**
248
+ * @notice Returns whether a node is marked as hot or cold
249
+ * @param tokenId Token ID to query
250
+ * @return isHot True if the node is hot, false if cold
251
+ * @dev Reverts if the token does not exist (NonexistentToken)
252
+ */
253
+ function isHotNode(uint256 tokenId) external view returns (bool isHot) {
254
+ if (_ownerOf(tokenId) == address(0)) revert NonexistentToken();
255
+ return _nodeData[tokenId].isHot;
256
+ }
257
+
258
+ /**
259
+ * @notice Get token ID for a given owner address
260
+ * @param owner The address to query
261
+ * @return tokenId The ID of the token owned by the address, or 0 if none
262
+ * @dev Iterates over token IDs. Since mints are sequential and users only own 1, this is a linear scan.
263
+ * In a production environment with millions of NFTs an off-chain indexer is preferred,
264
+ * but for this scale and testnet use-case, this convenience function works.
265
+ */
266
+ function tokenOfOwner(address owner) external view returns (uint256) {
267
+ if (owner == address(0)) revert InvalidRecipient();
268
+ if (balanceOf(owner) == 0) return 0;
269
+
270
+ // Since the user only has 1 NFT due to the mint restriction, we can find it
271
+ for (uint256 i = 1; i <= nextTokenId; ++i) {
272
+ if (_ownerOf(i) == owner) {
273
+ return i;
274
+ }
275
+ }
276
+ return 0; // Should never reach here if balanceOf > 0, but fallback
277
+ }
278
+
279
+ /**
280
+ * @notice Update the image URI for a token
281
+ * @param tokenId Token ID to update
282
+ * @param newImageURI New image URI (ipfs:// or https://)
283
+ * @dev Token owner or contract owner can call this function
284
+ * @dev Reverts if:
285
+ * - Token does not exist (NonexistentToken)
286
+ * - Caller is not authorized (NotAuthorized)
287
+ * @dev Emits ImageURIUpdated event
288
+ */
289
+ function setImageURI(
290
+ uint256 tokenId,
291
+ string calldata newImageURI
292
+ ) external {
293
+ address tokenOwner = _ownerOf(tokenId);
294
+ if (tokenOwner == address(0)) revert NonexistentToken();
295
+ if (msg.sender != tokenOwner && msg.sender != owner())
296
+ revert NotAuthorized();
297
+
298
+ _nodeData[tokenId].nodeImageURI = newImageURI;
299
+ emit ImageURIUpdated(tokenId, newImageURI);
300
+ }
301
+
302
+ /**
303
+ * @notice Update the social URL for a token
304
+ * @param tokenId Token ID to update
305
+ * @param newSocialURL New social URL (<=150 bytes)
306
+ * @dev Token owner or contract owner can call this function
307
+ * @dev Reverts if:
308
+ * - Token does not exist (NonexistentToken)
309
+ * - newSocialURL exceeds MAX_TEXT_BYTES (SocialURLTooLong)
310
+ * - Caller is not authorized (NotAuthorized)
311
+ * @dev Emits SocialURLUpdated event
312
+ */
313
+ function setSocialURL(
314
+ uint256 tokenId,
315
+ string calldata newSocialURL
316
+ ) external {
317
+ address tokenOwner = _ownerOf(tokenId);
318
+ if (tokenOwner == address(0)) revert NonexistentToken();
319
+ if (msg.sender != tokenOwner && msg.sender != owner())
320
+ revert NotAuthorized();
321
+ if (bytes(newSocialURL).length > MAX_TEXT_BYTES)
322
+ revert SocialURLTooLong();
323
+
324
+ _nodeData[tokenId].socialURL = newSocialURL;
325
+ emit SocialURLUpdated(tokenId, newSocialURL);
326
+ }
327
+
328
+ /**
329
+ * @notice Update the node name for a token
330
+ * @param tokenId Token ID to update
331
+ * @param newNodeName New node name (required, <=150 bytes)
332
+ * @dev Token owner or contract owner can call this function
333
+ * @dev Reverts if:
334
+ * - Token does not exist (NonexistentToken)
335
+ * - newNodeName is empty (NodeNameRequired)
336
+ * - newNodeName exceeds MAX_TEXT_BYTES (NodeNameTooLong)
337
+ * - Caller is not authorized (NotAuthorized)
338
+ * @dev Emits NodeNameUpdated event
339
+ */
340
+ function setNodeName(
341
+ uint256 tokenId,
342
+ string calldata newNodeName
343
+ ) external {
344
+ address tokenOwner = _ownerOf(tokenId);
345
+ if (tokenOwner == address(0)) revert NonexistentToken();
346
+ if (msg.sender != tokenOwner && msg.sender != owner())
347
+ revert NotAuthorized();
348
+ if (bytes(newNodeName).length == 0) revert NodeNameRequired();
349
+ if (bytes(newNodeName).length > MAX_TEXT_BYTES)
350
+ revert NodeNameTooLong();
351
+
352
+ _nodeData[tokenId].nodeName = newNodeName;
353
+ emit NodeNameUpdated(tokenId, newNodeName);
354
+ }
355
+
356
+ /**
357
+ * @notice Update the hot/cold status for a node
358
+ * @param tokenId Token ID to update
359
+ * @param isHot True to mark the node as hot, false to mark as cold
360
+ * @dev Contract owner can call this function
361
+ * @dev Reverts if:
362
+ * - Token does not exist (NonexistentToken)
363
+ * - Caller is not authorized (NotAuthorized)
364
+ * @dev Emits NodeHotStatusUpdated event
365
+ */
366
+ function setNodeHotStatus(uint256 tokenId, bool isHot) external {
367
+ address tokenOwner = _ownerOf(tokenId);
368
+ if (tokenOwner == address(0)) revert NonexistentToken();
369
+ if (msg.sender != owner()) revert NotAuthorized();
370
+
371
+ _nodeData[tokenId].isHot = isHot;
372
+ emit NodeHotStatusUpdated(tokenId, isHot);
373
+ }
374
+
375
+ /// -----------------------------------------------------------------------
376
+ /// Soulbound restrictions (disable transfers & approvals)
377
+ /// -----------------------------------------------------------------------
378
+
379
+ /**
380
+ * @notice Approve an address to transfer a token (disabled for soulbound NFTs)
381
+ * @dev Always reverts with SoulboundOperation error since tokens cannot be transferred
382
+ * @dev Parameters match ERC721 interface but are unused
383
+ */
384
+ function approve(
385
+ address /* operator */,
386
+ uint256 /* tokenId */
387
+ ) public pure override {
388
+ revert SoulboundOperation();
389
+ }
390
+
391
+ /**
392
+ * @notice Approve an operator for all tokens (disabled for soulbound NFTs)
393
+ * @dev Always reverts with SoulboundOperation error since tokens cannot be transferred
394
+ * @dev Parameters match ERC721 interface but are unused
395
+ */
396
+ function setApprovalForAll(
397
+ address /* operator */,
398
+ bool /* approved */
399
+ ) public pure override {
400
+ revert SoulboundOperation();
401
+ }
402
+
403
+ /**
404
+ * @notice Transfer a token (disabled for soulbound NFTs)
405
+ * @dev Always reverts with SoulboundOperation error since tokens are soulbound
406
+ * @dev Parameters match ERC721 interface but are unused
407
+ */
408
+ function transferFrom(
409
+ address /* from */,
410
+ address /* to */,
411
+ uint256 /* tokenId */
412
+ ) public pure override {
413
+ revert SoulboundOperation();
414
+ }
415
+
416
+ /// -----------------------------------------------------------------------
417
+ /// Burning
418
+ /// -----------------------------------------------------------------------
419
+
420
+ /**
421
+ * @notice Burn a token, permanently removing it from circulation
422
+ * @param tokenId Token ID to burn
423
+ * @dev Callable by token owner or contract owner
424
+ * @dev Reverts if:
425
+ * - Caller is not the token owner and not the contract owner (NotAuthorized)
426
+ * - Token does not exist
427
+ * @dev Deletes the associated node data after burning
428
+ */
429
+ function burn(uint256 tokenId) external {
430
+ address tokenOwner = ownerOf(tokenId);
431
+ if (msg.sender != tokenOwner && msg.sender != owner())
432
+ revert NotAuthorized();
433
+
434
+ _burn(tokenId);
435
+ delete _nodeData[tokenId];
436
+ }
437
+
438
+ /// -----------------------------------------------------------------------
439
+ /// Metadata (on-chain JSON)
440
+ /// -----------------------------------------------------------------------
441
+
442
+ /**
443
+ * @notice Return token metadata as base64-encoded JSON
444
+ * @param tokenId Token ID to query
445
+ * @return A base64-encoded JSON data URI containing the token metadata
446
+ * @dev Returns on-chain JSON metadata as a data URI (data:application/json;base64,...)
447
+ * @dev Includes token name, description, attributes (node name, social URL), and optional image
448
+ * @dev Reverts if the token does not exist (NonexistentToken)
449
+ */
450
+ function tokenURI(
451
+ uint256 tokenId
452
+ ) public view override returns (string memory) {
453
+ if (_ownerOf(tokenId) == address(0)) revert NonexistentToken();
454
+
455
+ NodeData memory d = _nodeData[tokenId];
456
+
457
+ string memory attributes = string.concat(
458
+ '[{"trait_type":"Node name","value":"',
459
+ _escapeJSON(d.nodeName),
460
+ '"}',
461
+ ',{"trait_type":"Social URL","value":"',
462
+ _escapeJSON(d.socialURL),
463
+ '"}]'
464
+ );
465
+
466
+ string memory imagePart = bytes(d.nodeImageURI).length == 0
467
+ ? ""
468
+ : string.concat(',"image":"', _escapeJSON(d.nodeImageURI), '"');
469
+
470
+ string memory json = string.concat(
471
+ '{"name":"Node #',
472
+ tokenId.toString(),
473
+ '","description":"Soulbound Node NFT",',
474
+ '"attributes":',
475
+ attributes,
476
+ imagePart,
477
+ "}"
478
+ );
479
+
480
+ return
481
+ string.concat(
482
+ "data:application/json;base64,",
483
+ Base64.encode(bytes(json))
484
+ );
485
+ }
486
+
487
+ /// -----------------------------------------------------------------------
488
+ /// Internal helpers
489
+ /// -----------------------------------------------------------------------
490
+
491
+ /**
492
+ * @notice Escape special JSON characters in a string
493
+ * @param s The string to escape
494
+ * @return The escaped string with backslashes added before quotes and backslashes
495
+ * @dev Used internally to safely embed strings in JSON metadata
496
+ * @dev Escapes double quotes (") and backslashes (\) by prefixing them with a backslash
497
+ */
498
+ function _escapeJSON(
499
+ string memory s
500
+ ) internal pure returns (string memory) {
501
+ bytes memory b = bytes(s);
502
+ bytes memory out = new bytes(b.length * 2);
503
+ uint256 j;
504
+
505
+ for (uint256 i = 0; i < b.length; i++) {
506
+ bytes1 c = b[i];
507
+ if (c == bytes1('"') || c == bytes1("\\")) {
508
+ out[j++] = bytes1("\\");
509
+ out[j++] = c;
510
+ } else {
511
+ out[j++] = c;
512
+ }
513
+ }
514
+
515
+ bytes memory trimmed = new bytes(j);
516
+ for (uint256 k = 0; k < j; k++) trimmed[k] = out[k];
517
+ return string(trimmed);
518
+ }
519
+ }