@venusprotocol/protocol-reserve 1.0.0-converters.1

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 (280) hide show
  1. package/README.md +75 -0
  2. package/artifacts/@openzeppelin/contracts/access/AccessControl.sol/AccessControl.dbg.json +4 -0
  3. package/artifacts/@openzeppelin/contracts/access/AccessControl.sol/AccessControl.json +215 -0
  4. package/artifacts/@openzeppelin/contracts/access/IAccessControl.sol/IAccessControl.dbg.json +4 -0
  5. package/artifacts/@openzeppelin/contracts/access/IAccessControl.sol/IAccessControl.json +183 -0
  6. package/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.dbg.json +4 -0
  7. package/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.json +297 -0
  8. package/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.dbg.json +4 -0
  9. package/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.json +194 -0
  10. package/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.dbg.json +4 -0
  11. package/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.json +233 -0
  12. package/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json +4 -0
  13. package/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.json +10 -0
  14. package/artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.dbg.json +4 -0
  15. package/artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.json +10 -0
  16. package/artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.dbg.json +4 -0
  17. package/artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.json +30 -0
  18. package/artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.dbg.json +4 -0
  19. package/artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.json +30 -0
  20. package/artifacts/@openzeppelin/contracts/utils/math/Math.sol/Math.dbg.json +4 -0
  21. package/artifacts/@openzeppelin/contracts/utils/math/Math.sol/Math.json +10 -0
  22. package/artifacts/@openzeppelin/contracts/utils/math/SignedMath.sol/SignedMath.dbg.json +4 -0
  23. package/artifacts/@openzeppelin/contracts/utils/math/SignedMath.sol/SignedMath.json +10 -0
  24. package/artifacts/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol/Ownable2StepUpgradeable.dbg.json +4 -0
  25. package/artifacts/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol/Ownable2StepUpgradeable.json +115 -0
  26. package/artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.dbg.json +4 -0
  27. package/artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.json +76 -0
  28. package/artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.dbg.json +4 -0
  29. package/artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.json +24 -0
  30. package/artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.dbg.json +4 -0
  31. package/artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.json +63 -0
  32. package/artifacts/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol/ReentrancyGuardUpgradeable.dbg.json +4 -0
  33. package/artifacts/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol/ReentrancyGuardUpgradeable.json +24 -0
  34. package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.dbg.json +4 -0
  35. package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.json +194 -0
  36. package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.dbg.json +4 -0
  37. package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.json +86 -0
  38. package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.dbg.json +4 -0
  39. package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.json +10 -0
  40. package/artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.dbg.json +4 -0
  41. package/artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.json +10 -0
  42. package/artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.dbg.json +4 -0
  43. package/artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.json +24 -0
  44. package/artifacts/@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol/AccessControlledV8.dbg.json +4 -0
  45. package/artifacts/@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol/AccessControlledV8.json +181 -0
  46. package/artifacts/@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol/IAccessControlManagerV8.dbg.json +4 -0
  47. package/artifacts/@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol/IAccessControlManagerV8.json +282 -0
  48. package/artifacts/@venusprotocol/isolated-pools/contracts/MaxLoopsLimitHelper.sol/MaxLoopsLimitHelper.dbg.json +4 -0
  49. package/artifacts/@venusprotocol/isolated-pools/contracts/MaxLoopsLimitHelper.sol/MaxLoopsLimitHelper.json +59 -0
  50. package/artifacts/@venusprotocol/oracle/contracts/ResilientOracle.sol/ResilientOracle.dbg.json +4 -0
  51. package/artifacts/@venusprotocol/oracle/contracts/ResilientOracle.sol/ResilientOracle.json +649 -0
  52. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/BoundValidatorInterface.dbg.json +4 -0
  53. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/BoundValidatorInterface.json +40 -0
  54. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/OracleInterface.dbg.json +4 -0
  55. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/OracleInterface.json +30 -0
  56. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/ResilientOracleInterface.dbg.json +4 -0
  57. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/ResilientOracleInterface.json +75 -0
  58. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/TwapInterface.dbg.json +4 -0
  59. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/TwapInterface.json +49 -0
  60. package/artifacts/@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol/VBep20Interface.dbg.json +4 -0
  61. package/artifacts/@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol/VBep20Interface.json +246 -0
  62. package/artifacts/@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol/MaxLoopsLimitHelper.dbg.json +4 -0
  63. package/artifacts/@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol/MaxLoopsLimitHelper.json +59 -0
  64. package/artifacts/build-info/09a7fbe40ee8fdfd62afe79292e77863.json +1 -0
  65. package/artifacts/contracts/Interfaces/IComptroller.sol/IComptroller.dbg.json +4 -0
  66. package/artifacts/contracts/Interfaces/IComptroller.sol/IComptroller.json +56 -0
  67. package/artifacts/contracts/Interfaces/IConverterNetwork.sol/IConverterNetwork.dbg.json +4 -0
  68. package/artifacts/contracts/Interfaces/IConverterNetwork.sol/IConverterNetwork.json +127 -0
  69. package/artifacts/contracts/Interfaces/IIncomeDestination.sol/IIncomeDestination.dbg.json +4 -0
  70. package/artifacts/contracts/Interfaces/IIncomeDestination.sol/IIncomeDestination.json +29 -0
  71. package/artifacts/contracts/Interfaces/IPoolRegistry.sol/IPoolRegistry.dbg.json +4 -0
  72. package/artifacts/contracts/Interfaces/IPoolRegistry.sol/IPoolRegistry.json +54 -0
  73. package/artifacts/contracts/Interfaces/IPrime.sol/IPrime.dbg.json +4 -0
  74. package/artifacts/contracts/Interfaces/IPrime.sol/IPrime.json +74 -0
  75. package/artifacts/contracts/Interfaces/IProtocolShareReserve.sol/IProtocolShareReserve.dbg.json +4 -0
  76. package/artifacts/contracts/Interfaces/IProtocolShareReserve.sol/IProtocolShareReserve.json +34 -0
  77. package/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFund.dbg.json +4 -0
  78. package/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFund.json +77 -0
  79. package/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFundGetters.dbg.json +4 -0
  80. package/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFundGetters.json +24 -0
  81. package/artifacts/contracts/Interfaces/IRiskFundConverter.sol/IRiskFundConverter.dbg.json +4 -0
  82. package/artifacts/contracts/Interfaces/IRiskFundConverter.sol/IRiskFundConverter.json +48 -0
  83. package/artifacts/contracts/Interfaces/IShortfall.sol/IShortfall.dbg.json +4 -0
  84. package/artifacts/contracts/Interfaces/IShortfall.sol/IShortfall.json +24 -0
  85. package/artifacts/contracts/Interfaces/IVToken.sol/IVToken.dbg.json +4 -0
  86. package/artifacts/contracts/Interfaces/IVToken.sol/IVToken.json +24 -0
  87. package/artifacts/contracts/Interfaces/IXVSVault.sol/IXVSVault.dbg.json +4 -0
  88. package/artifacts/contracts/Interfaces/IXVSVault.sol/IXVSVault.json +24 -0
  89. package/artifacts/contracts/ProtocolReserve/ProtocolShareReserve.sol/ProtocolShareReserve.dbg.json +4 -0
  90. package/artifacts/contracts/ProtocolReserve/ProtocolShareReserve.sol/ProtocolShareReserve.json +892 -0
  91. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/MaxLoopsLimitHelpersStorage.dbg.json +4 -0
  92. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/MaxLoopsLimitHelpersStorage.json +24 -0
  93. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/ReserveHelpersStorage.dbg.json +4 -0
  94. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/ReserveHelpersStorage.json +139 -0
  95. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/RiskFundV1Storage.dbg.json +4 -0
  96. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/RiskFundV1Storage.json +178 -0
  97. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/RiskFundV2Storage.dbg.json +4 -0
  98. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/RiskFundV2Storage.json +191 -0
  99. package/artifacts/contracts/ProtocolReserve/RiskFundV2.sol/RiskFundV2.dbg.json +4 -0
  100. package/artifacts/contracts/ProtocolReserve/RiskFundV2.sol/RiskFundV2.json +582 -0
  101. package/artifacts/contracts/ProtocolReserve/XVSVaultTreasury.sol/XVSVaultTreasury.dbg.json +4 -0
  102. package/artifacts/contracts/ProtocolReserve/XVSVaultTreasury.sol/XVSVaultTreasury.json +315 -0
  103. package/artifacts/contracts/Test/Mocks/MockACM.sol/MockACM.dbg.json +4 -0
  104. package/artifacts/contracts/Test/Mocks/MockACM.sol/MockACM.json +369 -0
  105. package/artifacts/contracts/Test/Mocks/MockArraySorter.sol/MockArraySorter.dbg.json +4 -0
  106. package/artifacts/contracts/Test/Mocks/MockArraySorter.sol/MockArraySorter.json +40 -0
  107. package/artifacts/contracts/Test/Mocks/MockConverter.sol/MockConverter.dbg.json +4 -0
  108. package/artifacts/contracts/Test/Mocks/MockConverter.sol/MockConverter.json +1199 -0
  109. package/artifacts/contracts/Test/Mocks/MockDeflationaryToken.sol/MockDeflatingToken.dbg.json +4 -0
  110. package/artifacts/contracts/Test/Mocks/MockDeflationaryToken.sol/MockDeflatingToken.json +332 -0
  111. package/artifacts/contracts/Test/Mocks/MockRiskFundConverter.sol/MockRiskFundConverter.dbg.json +4 -0
  112. package/artifacts/contracts/Test/Mocks/MockRiskFundConverter.sol/MockRiskFundConverter.json +1559 -0
  113. package/artifacts/contracts/Test/Mocks/MockToken.sol/MockToken.dbg.json +4 -0
  114. package/artifacts/contracts/Test/Mocks/MockToken.sol/MockToken.json +333 -0
  115. package/artifacts/contracts/TokenConverter/AbstractTokenConverter.sol/AbstractTokenConverter.dbg.json +4 -0
  116. package/artifacts/contracts/TokenConverter/AbstractTokenConverter.sol/AbstractTokenConverter.json +1085 -0
  117. package/artifacts/contracts/TokenConverter/ConverterNetwork.sol/ConverterNetwork.dbg.json +4 -0
  118. package/artifacts/contracts/TokenConverter/ConverterNetwork.sol/ConverterNetwork.json +457 -0
  119. package/artifacts/contracts/TokenConverter/IAbstractTokenConverter.sol/IAbstractTokenConverter.dbg.json +4 -0
  120. package/artifacts/contracts/TokenConverter/IAbstractTokenConverter.sol/IAbstractTokenConverter.json +344 -0
  121. package/artifacts/contracts/TokenConverter/RiskFundConverter.sol/RiskFundConverter.dbg.json +4 -0
  122. package/artifacts/contracts/TokenConverter/RiskFundConverter.sol/RiskFundConverter.json +1429 -0
  123. package/artifacts/contracts/TokenConverter/SingleTokenConverter.sol/SingleTokenConverter.dbg.json +4 -0
  124. package/artifacts/contracts/TokenConverter/SingleTokenConverter.sol/SingleTokenConverter.json +1145 -0
  125. package/contracts/Interfaces/IComptroller.sol +10 -0
  126. package/contracts/Interfaces/IConverterNetwork.sol +46 -0
  127. package/contracts/Interfaces/IIncomeDestination.sol +6 -0
  128. package/contracts/Interfaces/IPoolRegistry.sol +10 -0
  129. package/contracts/Interfaces/IPrime.sol +12 -0
  130. package/contracts/Interfaces/IProtocolShareReserve.sol +16 -0
  131. package/contracts/Interfaces/IRiskFund.sol +28 -0
  132. package/contracts/Interfaces/IRiskFundConverter.sol +8 -0
  133. package/contracts/Interfaces/IShortfall.sol +11 -0
  134. package/contracts/Interfaces/IVToken.sol +6 -0
  135. package/contracts/Interfaces/IXVSVault.sol +9 -0
  136. package/contracts/ProtocolReserve/ProtocolShareReserve.sol +547 -0
  137. package/contracts/ProtocolReserve/RiskFundStorage.sol +67 -0
  138. package/contracts/ProtocolReserve/RiskFundV2.sol +220 -0
  139. package/contracts/ProtocolReserve/XVSVaultTreasury.sol +95 -0
  140. package/contracts/Test/Mocks/MockACM.sol +93 -0
  141. package/contracts/Test/Mocks/MockArraySorter.sol +14 -0
  142. package/contracts/Test/Mocks/MockConverter.sol +69 -0
  143. package/contracts/Test/Mocks/MockDeflationaryToken.sol +113 -0
  144. package/contracts/Test/Mocks/MockRiskFundConverter.sol +45 -0
  145. package/contracts/Test/Mocks/MockToken.sol +30 -0
  146. package/contracts/TokenConverter/AbstractTokenConverter.sol +1022 -0
  147. package/contracts/TokenConverter/ConverterNetwork.sol +242 -0
  148. package/contracts/TokenConverter/IAbstractTokenConverter.sol +132 -0
  149. package/contracts/TokenConverter/RiskFundConverter.sol +436 -0
  150. package/contracts/TokenConverter/SingleTokenConverter.sol +77 -0
  151. package/contracts/Utils/ArrayHelpers.sol +41 -0
  152. package/contracts/Utils/Constants.sol +11 -0
  153. package/contracts/Utils/Validators.sol +26 -0
  154. package/deploy/001-risk-fund-converter.ts +124 -0
  155. package/deploy/1-deploy.ts +64 -0
  156. package/deployments/bscmainnet/.chainId +1 -0
  157. package/deployments/bscmainnet/DefaultProxyAdmin.json +257 -0
  158. package/deployments/bscmainnet/ProtocolShareReserve.json +1126 -0
  159. package/deployments/bscmainnet/ProtocolShareReserve_Implementation.json +1400 -0
  160. package/deployments/bscmainnet/ProtocolShareReserve_Proxy.json +261 -0
  161. package/deployments/bscmainnet/solcInputs/0e89febeebc7444140de8e67c9067d2c.json +78 -0
  162. package/deployments/bscmainnet/solcInputs/aee5f1db1180ece295e59c8f036fe600.json +90 -0
  163. package/deployments/bsctestnet/.chainId +1 -0
  164. package/deployments/bsctestnet/DefaultProxyAdmin.json +257 -0
  165. package/deployments/bsctestnet/ProtocolShareReserve.json +1126 -0
  166. package/deployments/bsctestnet/ProtocolShareReserve_Implementation.json +1400 -0
  167. package/deployments/bsctestnet/ProtocolShareReserve_Proxy.json +261 -0
  168. package/deployments/bsctestnet/solcInputs/0e89febeebc7444140de8e67c9067d2c.json +78 -0
  169. package/deployments/bsctestnet/solcInputs/aee5f1db1180ece295e59c8f036fe600.json +90 -0
  170. package/package.json +119 -0
  171. package/typechain/AbstractTokenConverter.d.ts +1516 -0
  172. package/typechain/AccessControl.d.ts +388 -0
  173. package/typechain/AccessControlledV8.d.ts +341 -0
  174. package/typechain/BoundValidatorInterface.d.ts +126 -0
  175. package/typechain/ContextUpgradeable.d.ts +92 -0
  176. package/typechain/ConverterNetwork.d.ts +721 -0
  177. package/typechain/ERC165.d.ts +116 -0
  178. package/typechain/ERC20.d.ts +441 -0
  179. package/typechain/IAbstractTokenConverter.d.ts +606 -0
  180. package/typechain/IAccessControl.d.ts +333 -0
  181. package/typechain/IAccessControlManagerV8.d.ts +504 -0
  182. package/typechain/IComptroller.d.ts +136 -0
  183. package/typechain/IConverterNetwork.d.ts +292 -0
  184. package/typechain/IERC165.d.ts +116 -0
  185. package/typechain/IERC20.d.ts +324 -0
  186. package/typechain/IERC20Metadata.d.ts +363 -0
  187. package/typechain/IERC20PermitUpgradeable.d.ts +187 -0
  188. package/typechain/IERC20Upgradeable.d.ts +324 -0
  189. package/typechain/IIncomeDestination.d.ts +122 -0
  190. package/typechain/IPoolRegistry.d.ts +155 -0
  191. package/typechain/IPrime.d.ts +197 -0
  192. package/typechain/IProtocolShareReserve.d.ts +127 -0
  193. package/typechain/IRiskFund.d.ts +200 -0
  194. package/typechain/IRiskFundConverter.d.ts +138 -0
  195. package/typechain/IRiskFundGetters.d.ts +103 -0
  196. package/typechain/IShortfall.d.ts +110 -0
  197. package/typechain/IVToken.d.ts +98 -0
  198. package/typechain/IXVSVault.d.ts +95 -0
  199. package/typechain/Initializable.d.ts +92 -0
  200. package/typechain/MaxLoopsLimitHelper.d.ts +128 -0
  201. package/typechain/MaxLoopsLimitHelpersStorage.d.ts +101 -0
  202. package/typechain/MockACM.d.ts +615 -0
  203. package/typechain/MockArraySorter.d.ts +118 -0
  204. package/typechain/MockConverter.d.ts +1705 -0
  205. package/typechain/MockDeflatingToken.d.ts +486 -0
  206. package/typechain/MockRiskFundConverter.d.ts +2193 -0
  207. package/typechain/MockToken.d.ts +505 -0
  208. package/typechain/OracleInterface.d.ts +98 -0
  209. package/typechain/Ownable2StepUpgradeable.d.ts +261 -0
  210. package/typechain/OwnableUpgradeable.d.ts +193 -0
  211. package/typechain/PausableUpgradeable.d.ts +129 -0
  212. package/typechain/ProtocolShareReserve.d.ts +1332 -0
  213. package/typechain/ReentrancyGuardUpgradeable.d.ts +92 -0
  214. package/typechain/ReserveHelpersStorage.d.ts +300 -0
  215. package/typechain/ResilientOracle.d.ts +1022 -0
  216. package/typechain/ResilientOracleInterface.d.ts +192 -0
  217. package/typechain/RiskFundConverter.d.ts +1949 -0
  218. package/typechain/RiskFundV1Storage.d.ts +353 -0
  219. package/typechain/RiskFundV2.d.ts +893 -0
  220. package/typechain/RiskFundV2Storage.d.ts +372 -0
  221. package/typechain/SingleTokenConverter.d.ts +1598 -0
  222. package/typechain/TwapInterface.d.ts +124 -0
  223. package/typechain/VBep20Interface.d.ts +379 -0
  224. package/typechain/XVSVaultTreasury.d.ts +515 -0
  225. package/typechain/common.d.ts +35 -0
  226. package/typechain/factories/AbstractTokenConverter__factory.ts +1105 -0
  227. package/typechain/factories/AccessControl__factory.ts +227 -0
  228. package/typechain/factories/AccessControlledV8__factory.ts +196 -0
  229. package/typechain/factories/BoundValidatorInterface__factory.ts +59 -0
  230. package/typechain/factories/ContextUpgradeable__factory.ts +39 -0
  231. package/typechain/factories/ConverterNetwork__factory.ts +502 -0
  232. package/typechain/factories/ERC165__factory.ts +39 -0
  233. package/typechain/factories/ERC20__factory.ts +340 -0
  234. package/typechain/factories/IAbstractTokenConverter__factory.ts +364 -0
  235. package/typechain/factories/IAccessControlManagerV8__factory.ts +301 -0
  236. package/typechain/factories/IAccessControl__factory.ts +198 -0
  237. package/typechain/factories/IComptroller__factory.ts +68 -0
  238. package/typechain/factories/IConverterNetwork__factory.ts +142 -0
  239. package/typechain/factories/IERC165__factory.ts +42 -0
  240. package/typechain/factories/IERC20Metadata__factory.ts +248 -0
  241. package/typechain/factories/IERC20PermitUpgradeable__factory.ts +105 -0
  242. package/typechain/factories/IERC20Upgradeable__factory.ts +209 -0
  243. package/typechain/factories/IERC20__factory.ts +203 -0
  244. package/typechain/factories/IIncomeDestination__factory.ts +44 -0
  245. package/typechain/factories/IPoolRegistry__factory.ts +66 -0
  246. package/typechain/factories/IPrime__factory.ts +83 -0
  247. package/typechain/factories/IProtocolShareReserve__factory.ts +53 -0
  248. package/typechain/factories/IRiskFundConverter__factory.ts +63 -0
  249. package/typechain/factories/IRiskFundGetters__factory.ts +39 -0
  250. package/typechain/factories/IRiskFund__factory.ts +89 -0
  251. package/typechain/factories/IShortfall__factory.ts +36 -0
  252. package/typechain/factories/IVToken__factory.ts +36 -0
  253. package/typechain/factories/IXVSVault__factory.ts +36 -0
  254. package/typechain/factories/Initializable__factory.ts +36 -0
  255. package/typechain/factories/MaxLoopsLimitHelper__factory.ts +74 -0
  256. package/typechain/factories/MaxLoopsLimitHelpersStorage__factory.ts +75 -0
  257. package/typechain/factories/MockACM__factory.ts +411 -0
  258. package/typechain/factories/MockArraySorter__factory.ts +85 -0
  259. package/typechain/factories/MockConverter__factory.ts +1242 -0
  260. package/typechain/factories/MockDeflatingToken__factory.ts +389 -0
  261. package/typechain/factories/MockRiskFundConverter__factory.ts +1625 -0
  262. package/typechain/factories/MockToken__factory.ts +398 -0
  263. package/typechain/factories/OracleInterface__factory.ts +45 -0
  264. package/typechain/factories/Ownable2StepUpgradeable__factory.ts +134 -0
  265. package/typechain/factories/OwnableUpgradeable__factory.ts +91 -0
  266. package/typechain/factories/PausableUpgradeable__factory.ts +78 -0
  267. package/typechain/factories/ProtocolShareReserve__factory.ts +957 -0
  268. package/typechain/factories/ReentrancyGuardUpgradeable__factory.ts +43 -0
  269. package/typechain/factories/ReserveHelpersStorage__factory.ts +188 -0
  270. package/typechain/factories/ResilientOracleInterface__factory.ts +94 -0
  271. package/typechain/factories/ResilientOracle__factory.ts +710 -0
  272. package/typechain/factories/RiskFundConverter__factory.ts +1491 -0
  273. package/typechain/factories/RiskFundV1Storage__factory.ts +223 -0
  274. package/typechain/factories/RiskFundV2Storage__factory.ts +236 -0
  275. package/typechain/factories/RiskFundV2__factory.ts +624 -0
  276. package/typechain/factories/SingleTokenConverter__factory.ts +1200 -0
  277. package/typechain/factories/TwapInterface__factory.ts +61 -0
  278. package/typechain/factories/VBep20Interface__factory.ts +261 -0
  279. package/typechain/factories/XVSVaultTreasury__factory.ts +365 -0
  280. package/typechain/index.ts +112 -0
@@ -0,0 +1,1022 @@
1
+ // SPDX-License-Identifier: BSD-3-Clause
2
+ pragma solidity 0.8.13;
3
+
4
+ import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
5
+ import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
6
+ import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol";
7
+ import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
8
+ import { ResilientOracle } from "@venusprotocol/oracle/contracts/ResilientOracle.sol";
9
+
10
+ import { MANTISSA_ONE, EXP_SCALE } from "../Utils/Constants.sol";
11
+ import { ensureNonzeroAddress, ensureNonzeroValue } from "../Utils/Validators.sol";
12
+ import { IAbstractTokenConverter } from "./IAbstractTokenConverter.sol";
13
+ import { IConverterNetwork } from "../Interfaces/IConverterNetwork.sol";
14
+
15
+ /// @title AbstractTokenConverter
16
+ /// @author Venus
17
+ /// @notice Abstract contract will be extended by SingleTokenConverter and RiskFundConverter
18
+ /*
19
+ * This contract specifies four functions for converting tokens, each applicable under following circumstances:
20
+ *
21
+ * Case I: TokenIn -> deflationary token, TokenOut -> deflationary token
22
+ * In this scenario, functions supporting fees can only be utilized to convert tokens which are:
23
+ * a. convertExactTokensSupportingFeeOnTransferTokens
24
+ * b. convertForExactTokensSupportingFeeOnTransferTokens
25
+ *
26
+ * Case II: TokenIn -> deflationary token, TokenOut -> non-deflationary token
27
+ * In this scenario, functions supporting fee can only be utilized to convert tokens which are:
28
+ * similar to Case I.
29
+ *
30
+ * Case III: TokenIn -> non-deflationary token, TokenOut -> deflationary token
31
+ * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:
32
+ * a. convertExactTokens
33
+ * b. convertForExactTokens
34
+ * c. convertExactTokensSupportingFeeOnTransferTokens
35
+ * d. convertForExactTokensSupportingFeeOnTransferTokens
36
+ *
37
+ * Case IV: TokenIn -> non-deflationary token, TokenOut -> non-deflationary token
38
+ * In this scenario, functions with or without supporting fee can be utilized to convert tokens which are:
39
+ * similar to Case III.
40
+ *
41
+ * ------------------------------------------------------------------------------------------------------------------------------------
42
+ * Example 1:-
43
+ * tokenInAddress - 0xaaaa.....
44
+ * tokenOutAddress - 0xbbbb.....
45
+ * tokenInAmount - 100
46
+ * tokenOutMinAmount - minimum amount desired by the user(let's say 70)
47
+ * Here user can use `convertExactTokens` or `convertExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary
48
+ * then `convertExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertExactTokens` is used).
49
+ * Now first tokenInAddress tokens will be transferred from the user to the contract, on the basis of amount
50
+ * received(as tokenInAddress can be deflationary token) tokenAmountOut will be calculated and will be transferred
51
+ * to the user and if amount sent is less than tokenOutMinAmount, tx will revert. If amount sent is satisfied(let's say
52
+ * 80 or even 70) then at last the actual amount received and the amount that was supposed to be received by the contract will
53
+ * be compared, if they differ then the whole tx will revert as user was supposed to use `convertExactTokensSupportingFeeOnTransferTokens`
54
+ * function for tokenIn as deflationary token.
55
+ *
56
+ * Example 2:-
57
+ * tokenInAddress - 0xaaaa.....
58
+ * tokenOutAddress - 0xbbbb.....
59
+ * tokenInMaxAmount - maximum amount user is willing to provide(let's say 100)
60
+ * tokenOutAmount - 70
61
+ * Here user can use `convertForExactTokens` or `convertForExactTokensSupportingFeeOnTransferTokens`, if tokenIn is deflationary
62
+ * then `convertForExactTokensSupportingFeeOnTransferTokens` should be used(let's suppose `convertForExactTokens` is used),
63
+ * which on the basis of tokenOutAmount provided will calculate tokenInAmount based on the tokens prices and will transfer
64
+ * tokens from the user to the contract, now the actual amount received(as tokenInAddress can be deflationary token) will be
65
+ * compared with tokenInMaxAmount if it is greater, tx will revert. If In amount is satisfied(let's say 90 or even 100) then
66
+ * new tokenOutAmount will be calculated, and tokenOutAddress tokens will be transferred to the user, but at last the
67
+ * old tokenOutAmount and new tokenOutAmount will be compared and if they differ whole tx will revert, because user was
68
+ * supposed to use `convertForExactTokensSupportingFeeOnTransferTokens` function for tokenIn as deflationary token.
69
+ * ------------------------------------------------------------------------------------------------------------------------------------
70
+ *
71
+ * This contract also supports private conversion between the converters:
72
+ * Private conversions:
73
+ * Private conversions is designed in order to convert the maximum amount of tokens received from PSR(to any converter) between
74
+ * existing converters to save incentive and lower the dependency of users for conversion. So Private Conversion will be executed
75
+ * by converters on it's own whenever funds are received from PSR. No incentive will be offered during private conversion.
76
+ *
77
+ * It will execute on updateAssetsState() function call in Converter Contracts. After this function call, converter will first
78
+ * check for the amount received. If base asset is received then it will be directly sent to the destination address and no private
79
+ * conversion will happen otherwise converter will interact with ConverterNetwork contract to find other valid converters who are providing the conversion for:
80
+ *
81
+ * tokenAddressIn: As asset received by that converter on updateAssetsState() function call.
82
+ * tokenAddressOut: As base asset of that converter.
83
+ *
84
+ * ConverterNetwork:
85
+ * This contract will contain all the converters, and will provide valid converters which can perform the execution according to tokenAddressIn
86
+ * and tokenAddressOut provided.
87
+ *
88
+ * findTokenConverters():
89
+ * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances
90
+ * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for users).
91
+ *
92
+ * findTokenConvertersForConverters():
93
+ * It will return an array of converter addresses along with their corresponding balances, sorted in descending order based on the converter's balances
94
+ * relative to tokenAddressOut. This function filter the converter addresses on the basis of the conversionAccess(for converters).
95
+ */
96
+
97
+ /// @custom:security-contact https://github.com/VenusProtocol/protocol-reserve#discussion
98
+ abstract contract AbstractTokenConverter is AccessControlledV8, IAbstractTokenConverter, ReentrancyGuardUpgradeable {
99
+ using SafeERC20Upgradeable for IERC20Upgradeable;
100
+
101
+ /// @notice Maximum incentive could be
102
+ uint256 public constant MAX_INCENTIVE = 0.5e18;
103
+
104
+ /// @notice Venus price oracle contract
105
+ ResilientOracle public priceOracle;
106
+
107
+ /// @notice conversion configurations for the existing pairs
108
+ /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig
109
+ mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;
110
+
111
+ /// @notice Address that all incoming tokens are transferred to
112
+ address public destinationAddress;
113
+
114
+ /// @notice Boolean for if conversion is paused
115
+ bool public conversionPaused;
116
+
117
+ /// @notice Address of the converterNetwork contract
118
+ IConverterNetwork public converterNetwork;
119
+
120
+ /// @dev This empty reserved space is put in place to allow future versions to add new
121
+ /// variables without shifting down storage in the inheritance chain.
122
+ /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
123
+ uint256[45] private __gap;
124
+
125
+ /// @notice Emitted when config is updated for tokens pair
126
+ event ConversionConfigUpdated(
127
+ address indexed tokenAddressIn,
128
+ address indexed tokenAddressOut,
129
+ uint256 oldIncentive,
130
+ uint256 newIncentive,
131
+ ConversionAccessibility oldAccess,
132
+ ConversionAccessibility newAccess
133
+ );
134
+ /// @notice Emitted when price oracle address is updated
135
+ event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);
136
+
137
+ /// @notice Emitted when destination address is updated
138
+ event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);
139
+
140
+ /// @notice Emitted when converterNetwork address is updated
141
+ event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);
142
+
143
+ /// @notice Emitted when exact amount of tokens are converted for tokens
144
+ event ConvertedExactTokens(uint256 amountIn, uint256 amountOut);
145
+
146
+ /// @notice Emitted when tokens are converted for exact amount of tokens
147
+ event ConvertedForExactTokens(uint256 amountIn, uint256 amountOut);
148
+
149
+ /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens
150
+ event ConvertedExactTokensSupportingFeeOnTransferTokens(uint256 amountIn, uint256 amountOut);
151
+
152
+ /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens
153
+ event ConvertedForExactTokensSupportingFeeOnTransferTokens(uint256 amountIn, uint256 amountOut);
154
+
155
+ /// @notice Emitted when conversion is paused
156
+ event ConversionPaused(address indexed sender);
157
+
158
+ /// @notice Emitted when conversion is unpaused
159
+ event ConversionResumed(address indexed sender);
160
+
161
+ /// @notice Event emitted when tokens are swept
162
+ event SweepToken(address indexed token, address indexed to, uint256 amount);
163
+
164
+ /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens
165
+ error AmountOutMismatched();
166
+
167
+ /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens
168
+ error AmountInMismatched();
169
+
170
+ /// @notice Thrown when given input amount is zero
171
+ error InsufficientInputAmount();
172
+
173
+ /// @notice Thrown when given output amount is zero
174
+ error InsufficientOutputAmount();
175
+
176
+ /// @notice Thrown when conversion is disabled or config does not exist for given pair
177
+ error ConversionConfigNotEnabled();
178
+
179
+ /// @notice Thrown when conversion is enabled only for private conversions
180
+ error ConversionEnabledOnlyForPrivateConversions();
181
+
182
+ /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut
183
+ error InvalidToAddress();
184
+
185
+ /// @notice Thrown when incentive is higher than the MAX_INCENTIVE
186
+ error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);
187
+
188
+ /// @notice Thrown when amountOut is lower than amountOutMin
189
+ error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);
190
+
191
+ /// @notice Thrown when amountIn is higher than amountInMax
192
+ error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);
193
+
194
+ /// @notice Thrown when conversion is paused
195
+ error ConversionTokensPaused();
196
+
197
+ /// @notice Thrown when conversion is Active
198
+ error ConversionTokensActive();
199
+
200
+ /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination
201
+ error InvalidTokenConfigAddresses();
202
+
203
+ /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa
204
+ error InsufficientPoolLiquidity();
205
+
206
+ /// @notice When address of the ConverterNetwork is not set or Zero address
207
+ error InvalidConverterNetwork();
208
+
209
+ /// @notice Thrown when trying to set non zero incentive for private conversion
210
+ error NonZeroIncentiveForPrivateConversion();
211
+
212
+ /// @notice Pause conversion of tokens
213
+ /// @custom:event Emits ConversionPaused on success
214
+ /// @custom:error ConversionTokensPaused thrown when conversion is already paused
215
+ /// @custom:access Restricted by ACM
216
+ function pauseConversion() external {
217
+ _checkAccessAllowed("pauseConversion()");
218
+ _checkConversionPaused();
219
+ conversionPaused = true;
220
+ emit ConversionPaused(msg.sender);
221
+ }
222
+
223
+ /// @notice Resume conversion of tokens.
224
+ /// @custom:event Emits ConversionResumed on success
225
+ /// @custom:error ConversionTokensActive thrown when conversion is already active
226
+ /// @custom:access Restricted by ACM
227
+ function resumeConversion() external {
228
+ _checkAccessAllowed("resumeConversion()");
229
+ if (!conversionPaused) {
230
+ revert ConversionTokensActive();
231
+ }
232
+
233
+ conversionPaused = false;
234
+ emit ConversionResumed(msg.sender);
235
+ }
236
+
237
+ /// @notice Sets a new price oracle
238
+ /// @param priceOracle_ Address of the new price oracle to set
239
+ /// @custom:access Only Governance
240
+ function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {
241
+ _setPriceOracle(priceOracle_);
242
+ }
243
+
244
+ /// @notice Sets a new destination address
245
+ /// @param destinationAddress_ The new destination address to be set
246
+ /// @custom:access Only Governance
247
+ function setDestination(address destinationAddress_) external onlyOwner {
248
+ _setDestination(destinationAddress_);
249
+ }
250
+
251
+ /// @notice Sets a converter network contract address
252
+ /// @param converterNetwork_ The converterNetwork address to be set
253
+ /// @custom:access Only Governance
254
+ function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {
255
+ _setConverterNetwork(converterNetwork_);
256
+ }
257
+
258
+ /// @notice Set the configuration for new or existing conversion pair
259
+ /// @param tokenAddressIn Address of tokenIn
260
+ /// @param tokenAddressOut Address of tokenOut
261
+ /// @param conversionConfig ConversionConfig config details to update
262
+ /// @custom:event Emits ConversionConfigUpdated event on success
263
+ /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager
264
+ /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero
265
+ /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion
266
+ /// @custom:access Controlled by AccessControlManager
267
+ function setConversionConfig(
268
+ address tokenAddressIn,
269
+ address tokenAddressOut,
270
+ ConversionConfig calldata conversionConfig
271
+ ) external {
272
+ _checkAccessAllowed("setConversionConfig(address,address,ConversionConfig)");
273
+ ensureNonzeroAddress(tokenAddressIn);
274
+ ensureNonzeroAddress(tokenAddressOut);
275
+
276
+ if (conversionConfig.incentive > MAX_INCENTIVE) {
277
+ revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);
278
+ }
279
+
280
+ if (
281
+ (tokenAddressIn == tokenAddressOut) ||
282
+ (tokenAddressIn != _getDestinationBaseAsset()) ||
283
+ conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE
284
+ ) {
285
+ revert InvalidTokenConfigAddresses();
286
+ }
287
+
288
+ if (
289
+ (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&
290
+ conversionConfig.incentive != 0
291
+ ) {
292
+ revert NonZeroIncentiveForPrivateConversion();
293
+ }
294
+
295
+ if (
296
+ ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||
297
+ (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&
298
+ (address(converterNetwork) == address(0))
299
+ ) {
300
+ revert InvalidConverterNetwork();
301
+ }
302
+
303
+ ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];
304
+
305
+ emit ConversionConfigUpdated(
306
+ tokenAddressIn,
307
+ tokenAddressOut,
308
+ configuration.incentive,
309
+ conversionConfig.incentive,
310
+ configuration.conversionAccess,
311
+ conversionConfig.conversionAccess
312
+ );
313
+
314
+ if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {
315
+ delete conversionConfigurations[tokenAddressIn][tokenAddressOut];
316
+ } else {
317
+ configuration.incentive = conversionConfig.incentive;
318
+ configuration.conversionAccess = conversionConfig.conversionAccess;
319
+ }
320
+ }
321
+
322
+ /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract
323
+ /// @dev Method does not support deflationary tokens transfer
324
+ /// @param amountInMantissa Amount of tokenAddressIn
325
+ /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output
326
+ /// @param tokenAddressIn Address of the token to convert
327
+ /// @param tokenAddressOut Address of the token to get after conversion
328
+ /// @param to Address of the tokenAddressOut receiver
329
+ /// @return actualAmountIn Actual amount transferred to destination
330
+ /// @return actualAmountOut Actual amount transferred to user
331
+ /// @custom:event Emits ConvertedExactTokens event on success
332
+ /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut
333
+ /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa
334
+ /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa
335
+ function convertExactTokens(
336
+ uint256 amountInMantissa,
337
+ uint256 amountOutMinMantissa,
338
+ address tokenAddressIn,
339
+ address tokenAddressOut,
340
+ address to
341
+ ) external nonReentrant returns (uint256 actualAmountIn, uint256 actualAmountOut) {
342
+ _checkConversionPaused();
343
+ if (to == tokenAddressIn || to == tokenAddressOut) {
344
+ revert InvalidToAddress();
345
+ }
346
+
347
+ (actualAmountIn, actualAmountOut) = _convertExactTokens(
348
+ amountInMantissa,
349
+ amountOutMinMantissa,
350
+ tokenAddressIn,
351
+ tokenAddressOut,
352
+ to
353
+ );
354
+
355
+ if (actualAmountIn != amountInMantissa) {
356
+ revert AmountInMismatched();
357
+ }
358
+
359
+ _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);
360
+
361
+ emit ConvertedExactTokens(actualAmountIn, actualAmountOut);
362
+ }
363
+
364
+ /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,
365
+ /// otherwise the amount is adjusted
366
+ /// @dev Method does not support deflationary tokens transfer
367
+ /// @param amountInMaxMantissa Max amount of tokenAddressIn
368
+ /// @param amountOutMantissa Amount of tokenAddressOut required as output
369
+ /// @param tokenAddressIn Address of the token to convert
370
+ /// @param tokenAddressOut Address of the token to get after conversion
371
+ /// @param to Address of the tokenAddressOut receiver
372
+ /// @return actualAmountIn Actual amount transferred to destination
373
+ /// @return actualAmountOut Actual amount transferred to user
374
+ /// @custom:event Emits ConvertedForExactTokens event on success
375
+ /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut
376
+ /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa
377
+ /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa
378
+ function convertForExactTokens(
379
+ uint256 amountInMaxMantissa,
380
+ uint256 amountOutMantissa,
381
+ address tokenAddressIn,
382
+ address tokenAddressOut,
383
+ address to
384
+ ) external nonReentrant returns (uint256 actualAmountIn, uint256 actualAmountOut) {
385
+ _checkConversionPaused();
386
+ if (to == tokenAddressIn || to == tokenAddressOut) {
387
+ revert InvalidToAddress();
388
+ }
389
+
390
+ (actualAmountIn, actualAmountOut) = _convertForExactTokens(
391
+ amountInMaxMantissa,
392
+ amountOutMantissa,
393
+ tokenAddressIn,
394
+ tokenAddressOut,
395
+ to
396
+ );
397
+
398
+ if (actualAmountOut != amountOutMantissa) {
399
+ revert AmountOutMismatched();
400
+ }
401
+
402
+ _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);
403
+ emit ConvertedForExactTokens(actualAmountIn, actualAmountOut);
404
+ }
405
+
406
+ /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract
407
+ /// @param amountInMantissa Amount of tokenAddressIn
408
+ /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output
409
+ /// @param tokenAddressIn Address of the token to convert
410
+ /// @param tokenAddressOut Address of the token to get after conversion
411
+ /// @param to Address of the tokenAddressOut receiver
412
+ /// @return actualAmountIn Actual amount transferred to destination
413
+ /// @return actualAmountOut Actual amount transferred to user
414
+ /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success
415
+ /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut
416
+ /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa
417
+ function convertExactTokensSupportingFeeOnTransferTokens(
418
+ uint256 amountInMantissa,
419
+ uint256 amountOutMinMantissa,
420
+ address tokenAddressIn,
421
+ address tokenAddressOut,
422
+ address to
423
+ ) external nonReentrant returns (uint256 actualAmountIn, uint256 actualAmountOut) {
424
+ _checkConversionPaused();
425
+ if (to == tokenAddressIn || to == tokenAddressOut) {
426
+ revert InvalidToAddress();
427
+ }
428
+
429
+ (actualAmountIn, actualAmountOut) = _convertExactTokens(
430
+ amountInMantissa,
431
+ amountOutMinMantissa,
432
+ tokenAddressIn,
433
+ tokenAddressOut,
434
+ to
435
+ );
436
+
437
+ _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);
438
+
439
+ emit ConvertedExactTokensSupportingFeeOnTransferTokens(actualAmountIn, actualAmountOut);
440
+ }
441
+
442
+ /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,
443
+ /// otherwise the amount is adjusted
444
+ /// @param amountInMaxMantissa Max amount of tokenAddressIn
445
+ /// @param amountOutMantissa Amount of tokenAddressOut required as output
446
+ /// @param tokenAddressIn Address of the token to convert
447
+ /// @param tokenAddressOut Address of the token to get after conversion
448
+ /// @param to Address of the tokenAddressOut receiver
449
+ /// @return actualAmountIn Actual amount transferred to destination
450
+ /// @return actualAmountOut Actual amount transferred to user
451
+ /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success
452
+ /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut
453
+ /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa
454
+ function convertForExactTokensSupportingFeeOnTransferTokens(
455
+ uint256 amountInMaxMantissa,
456
+ uint256 amountOutMantissa,
457
+ address tokenAddressIn,
458
+ address tokenAddressOut,
459
+ address to
460
+ ) external nonReentrant returns (uint256 actualAmountIn, uint256 actualAmountOut) {
461
+ _checkConversionPaused();
462
+ if (to == tokenAddressIn || to == tokenAddressOut) {
463
+ revert InvalidToAddress();
464
+ }
465
+
466
+ (actualAmountIn, actualAmountOut) = _convertForExactTokens(
467
+ amountInMaxMantissa,
468
+ amountOutMantissa,
469
+ tokenAddressIn,
470
+ tokenAddressOut,
471
+ to
472
+ );
473
+
474
+ _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);
475
+
476
+ emit ConvertedForExactTokensSupportingFeeOnTransferTokens(actualAmountIn, actualAmountOut);
477
+ }
478
+
479
+ /// @notice To sweep ERC20 tokens and transfer them to user(to address)
480
+ /// @param tokenAddress The address of the ERC-20 token to sweep
481
+ /// @param to The address to which tokens will be transferred
482
+ /// @param amount The amount to transfer
483
+ /// @custom:event Emits SweepToken event on success
484
+ /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero
485
+ /// @custom:access Only Governance
486
+ function sweepToken(
487
+ address tokenAddress,
488
+ address to,
489
+ uint256 amount
490
+ ) external onlyOwner nonReentrant {
491
+ ensureNonzeroAddress(tokenAddress);
492
+ ensureNonzeroAddress(to);
493
+ ensureNonzeroValue(amount);
494
+
495
+ IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);
496
+ preSweepToken(tokenAddress, amount);
497
+ token.safeTransfer(to, amount);
498
+
499
+ emit SweepToken(tokenAddress, to, amount);
500
+ }
501
+
502
+ /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn
503
+ /// @dev This function retrieves values without altering token prices.
504
+ /// @param amountInMantissa Amount of tokenAddressIn
505
+ /// @param tokenAddressIn Address of the token to convert
506
+ /// @param tokenAddressOut Address of the token to get after conversion
507
+ /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion
508
+ /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion
509
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
510
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
511
+ /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion
512
+ function getAmountOut(
513
+ uint256 amountInMantissa,
514
+ address tokenAddressIn,
515
+ address tokenAddressOut
516
+ ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {
517
+ if (
518
+ conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==
519
+ ConversionAccessibility.ONLY_FOR_CONVERTERS
520
+ ) {
521
+ revert ConversionEnabledOnlyForPrivateConversions();
522
+ }
523
+
524
+ uint256 tokenInToOutConversion;
525
+ (amountConvertedMantissa, amountOutMantissa, tokenInToOutConversion) = _getAmountOut(
526
+ amountInMantissa,
527
+ tokenAddressIn,
528
+ tokenAddressOut
529
+ );
530
+
531
+ uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);
532
+
533
+ /// If contract has less liquidity for tokenAddressOut than amountOutMantissa
534
+ if (maxTokenOutReserve < amountOutMantissa) {
535
+ amountConvertedMantissa =
536
+ ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /
537
+ tokenInToOutConversion; //round-up
538
+ amountOutMantissa = maxTokenOutReserve;
539
+ }
540
+ }
541
+
542
+ /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut
543
+ /// @dev This function retrieves values without altering token prices.
544
+ /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive
545
+ /// @param tokenAddressIn Address of the token to convert
546
+ /// @param tokenAddressOut Address of the token to get after conversion
547
+ /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion
548
+ /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion
549
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
550
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
551
+ /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion
552
+ function getAmountIn(
553
+ uint256 amountOutMantissa,
554
+ address tokenAddressIn,
555
+ address tokenAddressOut
556
+ ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {
557
+ if (
558
+ conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==
559
+ ConversionAccessibility.ONLY_FOR_CONVERTERS
560
+ ) {
561
+ revert ConversionEnabledOnlyForPrivateConversions();
562
+ }
563
+
564
+ uint256 tokenInToOutConversion;
565
+ (amountConvertedMantissa, amountInMantissa, tokenInToOutConversion) = _getAmountIn(
566
+ amountOutMantissa,
567
+ tokenAddressIn,
568
+ tokenAddressOut
569
+ );
570
+ uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);
571
+
572
+ /// If contract has less liquidity for tokenAddressOut than amountOutMantissa
573
+ if (maxTokenOutReserve < amountOutMantissa) {
574
+ amountInMantissa = ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up
575
+ amountConvertedMantissa = maxTokenOutReserve;
576
+ } else {
577
+ amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up
578
+ amountConvertedMantissa = amountOutMantissa;
579
+ }
580
+ }
581
+
582
+ /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn
583
+ /// @param amountInMantissa Amount of tokenAddressIn
584
+ /// @param tokenAddressIn Address of the token to convert
585
+ /// @param tokenAddressOut Address of the token to get after conversion
586
+ /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion
587
+ /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion
588
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
589
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
590
+ function getUpdatedAmountOut(
591
+ uint256 amountInMantissa,
592
+ address tokenAddressIn,
593
+ address tokenAddressOut
594
+ ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {
595
+ priceOracle.updateAssetPrice(tokenAddressIn);
596
+ priceOracle.updateAssetPrice(tokenAddressOut);
597
+ (amountConvertedMantissa, amountOutMantissa, ) = _getAmountOut(
598
+ amountInMantissa,
599
+ tokenAddressIn,
600
+ tokenAddressOut
601
+ );
602
+ }
603
+
604
+ /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut
605
+ /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive
606
+ /// @param tokenAddressIn Address of the token to convert
607
+ /// @param tokenAddressOut Address of the token to get after conversion
608
+ /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion
609
+ /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion
610
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
611
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
612
+ function getUpdatedAmountIn(
613
+ uint256 amountOutMantissa,
614
+ address tokenAddressIn,
615
+ address tokenAddressOut
616
+ ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {
617
+ priceOracle.updateAssetPrice(tokenAddressIn);
618
+ priceOracle.updateAssetPrice(tokenAddressOut);
619
+
620
+ (amountConvertedMantissa, amountInMantissa, ) = _getAmountIn(
621
+ amountOutMantissa,
622
+ tokenAddressIn,
623
+ tokenAddressOut
624
+ );
625
+ }
626
+
627
+ /// @notice This method updated the states of this contract after getting funds from PSR
628
+ /// after settling the amount(if any) through privateConversion between converters
629
+ /// @dev This function is called by protocolShareReserve
630
+ /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then it
631
+ /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address
632
+ /// @param comptroller Comptroller address (pool)
633
+ /// @param asset Asset address
634
+ function updateAssetsState(address comptroller, address asset) public nonReentrant {
635
+ uint256 balanceDiff = _updateAssetsState(comptroller, asset);
636
+ if (balanceDiff > 0) {
637
+ _privateConversion(comptroller, asset, balanceDiff);
638
+ }
639
+ }
640
+
641
+ /// @notice Get the balance for specific token
642
+ /// @param token Address of the token
643
+ /// @return tokenBalance Balance of the token the contract has
644
+ function balanceOf(address token) public view virtual returns (uint256 tokenBalance) {}
645
+
646
+ /// @notice Operations to perform before sweeping tokens
647
+ /// @param token Address of the token
648
+ /// @param amount Amount transferred to address(to)
649
+ function preSweepToken(address token, uint256 amount) internal virtual {}
650
+
651
+ /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut
652
+ /// @param amountInMantissa Amount of tokenAddressIn
653
+ /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output
654
+ /// @param tokenAddressIn Address of the token to convert
655
+ /// @param tokenAddressOut Address of the token to get after conversion
656
+ /// @param to Address of the tokenAddressOut receiver
657
+ /// @return actualAmountIn Actual amount of tokenAddressIn transferred
658
+ /// @return amountOutMantissa Actual amount of tokenAddressOut transferred
659
+ /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa
660
+ function _convertExactTokens(
661
+ uint256 amountInMantissa,
662
+ uint256 amountOutMinMantissa,
663
+ address tokenAddressIn,
664
+ address tokenAddressOut,
665
+ address to
666
+ ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {
667
+ _checkPrivateConversion(tokenAddressIn, tokenAddressOut);
668
+ actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);
669
+
670
+ (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);
671
+
672
+ if (amountOutMantissa < amountOutMinMantissa) {
673
+ revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);
674
+ }
675
+
676
+ _doTransferOut(tokenAddressOut, to, amountOutMantissa);
677
+ }
678
+
679
+ /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut
680
+ /// @param amountInMaxMantissa Max amount of tokenAddressIn
681
+ /// @param amountOutMantissa Amount of tokenAddressOut required as output
682
+ /// @param tokenAddressIn Address of the token to convert
683
+ /// @param tokenAddressOut Address of the token to get after conversion
684
+ /// @param to Address of the tokenAddressOut receiver
685
+ /// @return actualAmountIn Actual amount of tokenAddressIn transferred
686
+ /// @return actualAmountOut Actual amount of tokenAddressOut transferred
687
+ /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa
688
+ function _convertForExactTokens(
689
+ uint256 amountInMaxMantissa,
690
+ uint256 amountOutMantissa,
691
+ address tokenAddressIn,
692
+ address tokenAddressOut,
693
+ address to
694
+ ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {
695
+ _checkPrivateConversion(tokenAddressIn, tokenAddressOut);
696
+ (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);
697
+
698
+ actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);
699
+
700
+ if (actualAmountIn > amountInMaxMantissa) {
701
+ revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);
702
+ }
703
+
704
+ (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);
705
+
706
+ _doTransferOut(tokenAddressOut, to, actualAmountOut);
707
+ }
708
+
709
+ /// @notice return actualAmountOut from reserves for tokenAddressOut
710
+ /// @param tokenAddressOut Address of the token to get after conversion
711
+ /// @param to Address of the tokenAddressOut receiver
712
+ /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred
713
+ /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa
714
+ function _doTransferOut(
715
+ address tokenAddressOut,
716
+ address to,
717
+ uint256 amountConvertedMantissa
718
+ ) internal {
719
+ uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);
720
+
721
+ /// If contract has less liquidity for tokenAddressOut than amountOutMantissa
722
+ if (maxTokenOutReserve < amountConvertedMantissa) {
723
+ revert InsufficientPoolLiquidity();
724
+ }
725
+
726
+ _preTransferHook(tokenAddressOut, amountConvertedMantissa);
727
+
728
+ IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);
729
+ tokenOut.safeTransfer(to, amountConvertedMantissa);
730
+ }
731
+
732
+ /// @notice Transfer tokenAddressIn from user to destination
733
+ /// @param tokenAddressIn Address of the token to convert
734
+ /// @param amountInMantissa Amount of tokenAddressIn
735
+ /// @return actualAmountIn Actual amount transferred to destination
736
+ function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {
737
+ IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);
738
+ uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);
739
+ tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);
740
+ uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);
741
+ actualAmountIn = balanceAfterDestination - balanceBeforeDestination;
742
+ }
743
+
744
+ /// @notice Sets a new price oracle
745
+ /// @param priceOracle_ Address of the new price oracle to set
746
+ /// @custom:event Emits PriceOracleUpdated event on success
747
+ /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero
748
+ function _setPriceOracle(ResilientOracle priceOracle_) internal {
749
+ ensureNonzeroAddress(address(priceOracle_));
750
+ emit PriceOracleUpdated(priceOracle, priceOracle_);
751
+ priceOracle = priceOracle_;
752
+ }
753
+
754
+ /// @notice Sets a new destination address
755
+ /// @param destinationAddress_ The new destination address to be set
756
+ /// @custom:event Emits DestinationAddressUpdated event on success
757
+ /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero
758
+ function _setDestination(address destinationAddress_) internal {
759
+ ensureNonzeroAddress(destinationAddress_);
760
+ emit DestinationAddressUpdated(destinationAddress, destinationAddress_);
761
+ destinationAddress = destinationAddress_;
762
+ }
763
+
764
+ /// @notice Sets a converter network contract address
765
+ /// @param converterNetwork_ The converterNetwork address to be set
766
+ /// @custom:event Emits ConverterNetworkAddressUpdated event on success
767
+ /// @custom:error ZeroAddressNotAllowed is thrown when address is zero
768
+ function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {
769
+ ensureNonzeroAddress(address(converterNetwork_));
770
+ emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));
771
+ converterNetwork = converterNetwork_;
772
+ }
773
+
774
+ /// @notice Hook to perform after converting tokens
775
+ /// @param tokenAddressIn Address of the token to convert
776
+ /// @param tokenAddressOut Address of the token to get after conversion
777
+ /// @param amountIn Amount of tokenIn converted
778
+ /// @param amountOut Amount of tokenOut converted
779
+ function _postConversionHook(
780
+ address tokenAddressIn,
781
+ address tokenAddressOut,
782
+ uint256 amountIn,
783
+ uint256 amountOut
784
+ ) internal virtual {}
785
+
786
+ /// @param accessControlManager_ Access control manager contract address
787
+ /// @param priceOracle_ Resilient oracle address
788
+ /// @param destinationAddress_ Address at all incoming tokens will transferred to
789
+ function __AbstractTokenConverter_init(
790
+ address accessControlManager_,
791
+ ResilientOracle priceOracle_,
792
+ address destinationAddress_
793
+ ) internal onlyInitializing {
794
+ __AccessControlled_init(accessControlManager_);
795
+ __ReentrancyGuard_init();
796
+ __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_);
797
+ }
798
+
799
+ /// @param priceOracle_ Resilient oracle address
800
+ /// @param destinationAddress_ Address at all incoming tokens will transferred to
801
+ function __AbstractTokenConverter_init_unchained(ResilientOracle priceOracle_, address destinationAddress_)
802
+ internal
803
+ onlyInitializing
804
+ {
805
+ _setPriceOracle(priceOracle_);
806
+ _setDestination(destinationAddress_);
807
+ conversionPaused = false;
808
+ }
809
+
810
+ /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller
811
+ /// @param comptroller Comptroller address (pool)
812
+ /// @param asset Asset address
813
+ /// @return Amount of asset, for _privateConversion
814
+ function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}
815
+
816
+ /// @dev This method is used to convert asset into base asset by converting them with other converters which supports the pair and transfer the funds to
817
+ /// destination contract as destination's base asset
818
+ /// @param comptroller Comptroller address (pool)
819
+ /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset
820
+ /// @param amountToConvert Amount of the tokenAddressOut transferred to converter
821
+ function _privateConversion(
822
+ address comptroller,
823
+ address tokenAddressOut,
824
+ uint256 amountToConvert
825
+ ) internal {
826
+ address tokenAddressIn = _getDestinationBaseAsset();
827
+ address _destinationAddress = destinationAddress;
828
+ uint256 convertedTokenInBalance;
829
+ if (address(converterNetwork) != address(0)) {
830
+ (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork
831
+ .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);
832
+ uint256 convertersLength = converterAddresses.length;
833
+ for (uint256 i; i < convertersLength; ) {
834
+ if (converterBalances[i] == 0) break;
835
+ (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(
836
+ converterBalances[i],
837
+ tokenAddressOut,
838
+ tokenAddressIn
839
+ );
840
+ if (amountIn > amountToConvert) {
841
+ amountIn = amountToConvert;
842
+ }
843
+
844
+ uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);
845
+
846
+ IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);
847
+ IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(
848
+ amountIn,
849
+ 0,
850
+ tokenAddressOut,
851
+ tokenAddressIn,
852
+ _destinationAddress
853
+ );
854
+
855
+ uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);
856
+ amountToConvert -= amountIn;
857
+ convertedTokenInBalance += (balanceAfter - balanceBefore);
858
+
859
+ if (amountToConvert == 0) break;
860
+ unchecked {
861
+ ++i;
862
+ }
863
+ }
864
+ }
865
+
866
+ _postPrivateConversionHook(
867
+ comptroller,
868
+ tokenAddressIn,
869
+ convertedTokenInBalance,
870
+ tokenAddressOut,
871
+ amountToConvert
872
+ );
873
+ }
874
+
875
+ /// @dev This hook is used to update states for the converter after the privateConversion
876
+ /// @param comptroller Comptroller address (pool)
877
+ /// @param tokenAddressIn Address of the destination's base asset
878
+ /// @param convertedTokenInBalance Amount of the base asset received after the conversion
879
+ /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset
880
+ /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter
881
+ function _postPrivateConversionHook(
882
+ address comptroller,
883
+ address tokenAddressIn,
884
+ uint256 convertedTokenInBalance,
885
+ address tokenAddressOut,
886
+ uint256 convertedTokenOutBalance
887
+ ) internal virtual {}
888
+
889
+ /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user
890
+ /// @param tokenOutAddress Address of the asset to be transferred to the user
891
+ /// @param amountOut Amount of tokenAddressOut transferred from this converter
892
+ function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}
893
+
894
+ /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn
895
+ /// @dev This function retrieves values without altering token prices.
896
+ /// @param amountInMantissa Amount of tokenAddressIn
897
+ /// @param tokenAddressIn Address of the token to convert
898
+ /// @param tokenAddressOut Address of the token to get after conversion
899
+ /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion
900
+ /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion
901
+ /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price
902
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
903
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
904
+ function _getAmountOut(
905
+ uint256 amountInMantissa,
906
+ address tokenAddressIn,
907
+ address tokenAddressOut
908
+ )
909
+ internal
910
+ view
911
+ returns (
912
+ uint256 amountConvertedMantissa,
913
+ uint256 amountOutMantissa,
914
+ uint256 tokenInToOutConversion
915
+ )
916
+ {
917
+ if (amountInMantissa == 0) {
918
+ revert InsufficientInputAmount();
919
+ }
920
+
921
+ ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];
922
+
923
+ if (configuration.conversionAccess == ConversionAccessibility.NONE) {
924
+ revert ConversionConfigNotEnabled();
925
+ }
926
+
927
+ uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);
928
+ uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);
929
+
930
+ uint256 incentive = configuration.incentive;
931
+ if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {
932
+ incentive = 0;
933
+ }
934
+
935
+ /// amount of tokenAddressOut after including incentive
936
+ uint256 conversionWithIncentive = MANTISSA_ONE + incentive;
937
+ /// conversion rate after considering incentive(conversionWithIncentive)
938
+
939
+ amountOutMantissa =
940
+ (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /
941
+ (tokenOutUnderlyingPrice * EXP_SCALE);
942
+ amountConvertedMantissa = amountInMantissa;
943
+
944
+ tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;
945
+ }
946
+
947
+ /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut
948
+ /// @dev This function retrieves values without altering token prices.
949
+ /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive
950
+ /// @param tokenAddressIn Address of the token to convert
951
+ /// @param tokenAddressOut Address of the token to get after conversion
952
+ /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion
953
+ /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion
954
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
955
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
956
+ function _getAmountIn(
957
+ uint256 amountOutMantissa,
958
+ address tokenAddressIn,
959
+ address tokenAddressOut
960
+ )
961
+ internal
962
+ view
963
+ returns (
964
+ uint256 amountConvertedMantissa,
965
+ uint256 amountInMantissa,
966
+ uint256 tokenInToOutConversion
967
+ )
968
+ {
969
+ if (amountOutMantissa == 0) {
970
+ revert InsufficientOutputAmount();
971
+ }
972
+
973
+ ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];
974
+
975
+ if (configuration.conversionAccess == ConversionAccessibility.NONE) {
976
+ revert ConversionConfigNotEnabled();
977
+ }
978
+
979
+ uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);
980
+ uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);
981
+
982
+ uint256 incentive = configuration.incentive;
983
+ if ((address(converterNetwork) != address(0)) && (converterNetwork.isTokenConverter(msg.sender))) {
984
+ incentive = 0;
985
+ }
986
+
987
+ /// amount of tokenAddressOut after including incentive
988
+ uint256 conversionWithIncentive = MANTISSA_ONE + incentive;
989
+ /// conversion rate after considering incentive(conversionWithIncentive)
990
+ tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;
991
+
992
+ amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up
993
+ amountConvertedMantissa = amountOutMantissa;
994
+ }
995
+
996
+ /// @notice Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag
997
+ /// @param tokenAddressIn Address of the token to convert
998
+ /// @param tokenAddressOut Address of the token to get after conversion
999
+ /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion
1000
+ function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {
1001
+ bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);
1002
+ if (
1003
+ (!(isConverter) &&
1004
+ (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==
1005
+ ConversionAccessibility.ONLY_FOR_CONVERTERS))
1006
+ ) {
1007
+ revert ConversionEnabledOnlyForPrivateConversions();
1008
+ }
1009
+ }
1010
+
1011
+ /// @notice To check, is conversion paused
1012
+ /// @custom:error ConversionTokensPaused is thrown when token conversion is paused
1013
+ function _checkConversionPaused() internal view {
1014
+ if (conversionPaused) {
1015
+ revert ConversionTokensPaused();
1016
+ }
1017
+ }
1018
+
1019
+ /// @notice Get base asset address of the destination contract
1020
+ /// @return Address of the base asset
1021
+ function _getDestinationBaseAsset() internal view virtual returns (address) {}
1022
+ }