@venusprotocol/protocol-reserve 1.3.0 → 1.4.0-dev.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 (311) hide show
  1. package/README.md +6 -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 +1 -1
  5. package/artifacts/@openzeppelin/contracts/access/Ownable.sol/Ownable.dbg.json +4 -0
  6. package/artifacts/@openzeppelin/contracts/access/Ownable.sol/Ownable.json +63 -0
  7. package/artifacts/@openzeppelin/contracts/interfaces/IERC1967.sol/IERC1967.dbg.json +4 -0
  8. package/artifacts/@openzeppelin/contracts/interfaces/IERC1967.sol/IERC1967.json +56 -0
  9. package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC1822.sol/IERC1822Proxiable.dbg.json +4 -0
  10. package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC1822.sol/IERC1822Proxiable.json +24 -0
  11. package/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol/ERC1967Upgrade.dbg.json +4 -0
  12. package/artifacts/@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol/ERC1967Upgrade.json +56 -0
  13. package/artifacts/@openzeppelin/contracts/proxy/Proxy.sol/Proxy.dbg.json +4 -0
  14. package/artifacts/@openzeppelin/contracts/proxy/Proxy.sol/Proxy.json +19 -0
  15. package/artifacts/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.dbg.json +4 -0
  16. package/artifacts/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.json +80 -0
  17. package/artifacts/@openzeppelin/contracts/proxy/beacon/IBeacon.sol/IBeacon.dbg.json +4 -0
  18. package/artifacts/{contracts/Interfaces/ComptrollerInterface.sol/ComptrollerInterface.json → @openzeppelin/contracts/proxy/beacon/IBeacon.sol/IBeacon.json} +5 -5
  19. package/artifacts/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.dbg.json +4 -0
  20. package/artifacts/@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.json +113 -0
  21. package/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.dbg.json +1 -1
  22. package/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.dbg.json +1 -1
  23. package/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.dbg.json +1 -1
  24. package/artifacts/@openzeppelin/contracts/utils/Address.sol/Address.dbg.json +4 -0
  25. package/artifacts/@openzeppelin/contracts/utils/Address.sol/Address.json +10 -0
  26. package/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json +1 -1
  27. package/artifacts/@openzeppelin/contracts/utils/StorageSlot.sol/StorageSlot.dbg.json +4 -0
  28. package/artifacts/@openzeppelin/contracts/utils/StorageSlot.sol/StorageSlot.json +10 -0
  29. package/artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.dbg.json +4 -0
  30. package/artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.json +10 -0
  31. package/artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.dbg.json +4 -0
  32. package/artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.json +30 -0
  33. package/artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.dbg.json +4 -0
  34. package/artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.json +30 -0
  35. package/artifacts/@openzeppelin/contracts/utils/math/Math.sol/Math.dbg.json +4 -0
  36. package/artifacts/@openzeppelin/contracts/utils/math/Math.sol/Math.json +10 -0
  37. package/artifacts/@openzeppelin/contracts/utils/math/SignedMath.sol/SignedMath.dbg.json +4 -0
  38. package/artifacts/@openzeppelin/contracts/utils/math/SignedMath.sol/SignedMath.json +10 -0
  39. package/artifacts/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol/Ownable2StepUpgradeable.dbg.json +1 -1
  40. package/artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.dbg.json +1 -1
  41. package/artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.dbg.json +1 -1
  42. package/artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.dbg.json +4 -0
  43. package/artifacts/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol/PausableUpgradeable.json +63 -0
  44. package/artifacts/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol/ReentrancyGuardUpgradeable.dbg.json +1 -1
  45. package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.dbg.json +1 -1
  46. package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.dbg.json +1 -1
  47. package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.dbg.json +1 -1
  48. package/artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.dbg.json +1 -1
  49. package/artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.dbg.json +1 -1
  50. package/artifacts/@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol/AccessControlledV8.dbg.json +1 -1
  51. package/artifacts/@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol/IAccessControlManagerV8.dbg.json +1 -1
  52. package/artifacts/@venusprotocol/oracle/contracts/ResilientOracle.sol/ResilientOracle.dbg.json +4 -0
  53. package/artifacts/@venusprotocol/oracle/contracts/ResilientOracle.sol/ResilientOracle.json +649 -0
  54. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/BoundValidatorInterface.dbg.json +4 -0
  55. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/BoundValidatorInterface.json +40 -0
  56. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/OracleInterface.dbg.json +4 -0
  57. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/OracleInterface.json +30 -0
  58. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/ResilientOracleInterface.dbg.json +4 -0
  59. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/ResilientOracleInterface.json +75 -0
  60. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/TwapInterface.dbg.json +4 -0
  61. package/artifacts/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/TwapInterface.json +49 -0
  62. package/artifacts/@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol/VBep20Interface.dbg.json +4 -0
  63. package/artifacts/@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol/VBep20Interface.json +246 -0
  64. package/artifacts/@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol/MaxLoopsLimitHelper.dbg.json +1 -1
  65. package/artifacts/build-info/e6962244d9988e3e4bb55e591cf3b5d8.json +1 -0
  66. package/artifacts/contracts/Interfaces/IComptroller.sol/IComptroller.dbg.json +4 -0
  67. package/artifacts/contracts/Interfaces/IComptroller.sol/IComptroller.json +56 -0
  68. package/artifacts/contracts/Interfaces/IConverterNetwork.sol/IConverterNetwork.dbg.json +4 -0
  69. package/artifacts/contracts/Interfaces/IConverterNetwork.sol/IConverterNetwork.json +127 -0
  70. package/artifacts/contracts/Interfaces/IIncomeDestination.sol/IIncomeDestination.dbg.json +1 -1
  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/IProtocolShareReserve.sol/IProtocolShareReserve.dbg.json +1 -1
  74. package/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFund.dbg.json +4 -0
  75. package/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFund.json +77 -0
  76. package/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFundGetters.dbg.json +4 -0
  77. package/artifacts/contracts/Interfaces/IRiskFund.sol/IRiskFundGetters.json +24 -0
  78. package/artifacts/contracts/Interfaces/IRiskFundConverter.sol/IRiskFundConverter.dbg.json +4 -0
  79. package/artifacts/contracts/Interfaces/{PoolRegistryInterface.sol/PoolRegistryInterface.json → IRiskFundConverter.sol/IRiskFundConverter.json} +23 -10
  80. package/artifacts/contracts/Interfaces/IShortfall.sol/IShortfall.dbg.json +4 -0
  81. package/artifacts/contracts/Interfaces/IShortfall.sol/IShortfall.json +24 -0
  82. package/artifacts/contracts/Interfaces/IVToken.sol/IVToken.dbg.json +1 -1
  83. package/artifacts/contracts/Interfaces/IXVSVault.sol/IXVSVault.dbg.json +4 -0
  84. package/artifacts/contracts/Interfaces/IXVSVault.sol/IXVSVault.json +24 -0
  85. package/artifacts/contracts/ProtocolReserve/ProtocolShareReserve.sol/ProtocolShareReserve.dbg.json +1 -1
  86. package/artifacts/contracts/ProtocolReserve/ProtocolShareReserve.sol/ProtocolShareReserve.json +7 -2
  87. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/MaxLoopsLimitHelpersStorage.dbg.json +4 -0
  88. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/MaxLoopsLimitHelpersStorage.json +24 -0
  89. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/ReserveHelpersStorage.dbg.json +4 -0
  90. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/ReserveHelpersStorage.json +139 -0
  91. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/RiskFundV1Storage.dbg.json +4 -0
  92. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/RiskFundV1Storage.json +178 -0
  93. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/RiskFundV2Storage.dbg.json +4 -0
  94. package/artifacts/contracts/ProtocolReserve/RiskFundStorage.sol/RiskFundV2Storage.json +191 -0
  95. package/artifacts/contracts/ProtocolReserve/RiskFundV2.sol/RiskFundV2.dbg.json +4 -0
  96. package/artifacts/contracts/ProtocolReserve/RiskFundV2.sol/RiskFundV2.json +630 -0
  97. package/artifacts/contracts/ProtocolReserve/XVSVaultTreasury.sol/XVSVaultTreasury.dbg.json +4 -0
  98. package/artifacts/contracts/ProtocolReserve/XVSVaultTreasury.sol/XVSVaultTreasury.json +315 -0
  99. package/artifacts/contracts/Test/Mocks/MockACM.sol/MockACM.dbg.json +4 -0
  100. package/artifacts/contracts/Test/Mocks/MockACM.sol/MockACM.json +369 -0
  101. package/artifacts/contracts/Test/Mocks/MockArraySorter.sol/MockArraySorter.dbg.json +4 -0
  102. package/artifacts/contracts/Test/Mocks/MockArraySorter.sol/MockArraySorter.json +40 -0
  103. package/artifacts/contracts/Test/Mocks/MockConverter.sol/MockConverter.dbg.json +4 -0
  104. package/artifacts/contracts/Test/Mocks/MockConverter.sol/MockConverter.json +1395 -0
  105. package/artifacts/contracts/Test/Mocks/MockDeflationaryToken.sol/MockDeflatingToken.dbg.json +4 -0
  106. package/artifacts/contracts/Test/Mocks/MockDeflationaryToken.sol/MockDeflatingToken.json +332 -0
  107. package/artifacts/contracts/Test/Mocks/MockRiskFundConverter.sol/MockRiskFundConverter.dbg.json +4 -0
  108. package/artifacts/contracts/Test/Mocks/MockRiskFundConverter.sol/MockRiskFundConverter.json +1761 -0
  109. package/artifacts/contracts/Test/Mocks/MockToken.sol/MockToken.dbg.json +1 -1
  110. package/artifacts/contracts/Test/Mocks/MockToken.sol/MockToken.json +20 -2
  111. package/artifacts/contracts/TokenConverter/AbstractTokenConverter.sol/AbstractTokenConverter.dbg.json +4 -0
  112. package/artifacts/contracts/TokenConverter/AbstractTokenConverter.sol/AbstractTokenConverter.json +1276 -0
  113. package/artifacts/contracts/TokenConverter/ConverterNetwork.sol/ConverterNetwork.dbg.json +4 -0
  114. package/artifacts/contracts/TokenConverter/ConverterNetwork.sol/ConverterNetwork.json +457 -0
  115. package/artifacts/contracts/TokenConverter/IAbstractTokenConverter.sol/IAbstractTokenConverter.dbg.json +4 -0
  116. package/artifacts/contracts/TokenConverter/IAbstractTokenConverter.sol/IAbstractTokenConverter.json +446 -0
  117. package/artifacts/contracts/TokenConverter/RiskFundConverter.sol/RiskFundConverter.dbg.json +4 -0
  118. package/artifacts/contracts/TokenConverter/RiskFundConverter.sol/RiskFundConverter.json +1631 -0
  119. package/artifacts/contracts/TokenConverter/SingleTokenConverter.sol/SingleTokenConverter.dbg.json +4 -0
  120. package/artifacts/contracts/TokenConverter/SingleTokenConverter.sol/SingleTokenConverter.json +1390 -0
  121. package/contracts/Interfaces/IComptroller.sol +10 -0
  122. package/contracts/Interfaces/IConverterNetwork.sol +46 -0
  123. package/contracts/Interfaces/IPoolRegistry.sol +10 -0
  124. package/contracts/Interfaces/IRiskFund.sol +28 -0
  125. package/contracts/Interfaces/IRiskFundConverter.sol +8 -0
  126. package/contracts/Interfaces/IShortfall.sol +11 -0
  127. package/contracts/Interfaces/IXVSVault.sol +9 -0
  128. package/contracts/ProtocolReserve/ProtocolShareReserve.sol +15 -12
  129. package/contracts/ProtocolReserve/RiskFundStorage.sol +67 -0
  130. package/contracts/ProtocolReserve/RiskFundV2.sol +253 -0
  131. package/contracts/ProtocolReserve/XVSVaultTreasury.sol +95 -0
  132. package/contracts/Test/Mocks/MockACM.sol +94 -0
  133. package/contracts/Test/Mocks/MockArraySorter.sol +14 -0
  134. package/contracts/Test/Mocks/MockConverter.sol +70 -0
  135. package/contracts/Test/Mocks/MockDeflationaryToken.sol +113 -0
  136. package/contracts/Test/Mocks/MockRiskFundConverter.sol +45 -0
  137. package/contracts/Test/Mocks/MockToken.sol +4 -0
  138. package/contracts/Test/imports.sol +11 -0
  139. package/contracts/TokenConverter/AbstractTokenConverter.sol +1167 -0
  140. package/contracts/TokenConverter/ConverterNetwork.sol +243 -0
  141. package/contracts/TokenConverter/IAbstractTokenConverter.sol +178 -0
  142. package/contracts/TokenConverter/RiskFundConverter.sol +449 -0
  143. package/contracts/TokenConverter/SingleTokenConverter.sol +103 -0
  144. package/contracts/Utils/ArrayHelpers.sol +41 -0
  145. package/deployments/bscmainnet/BTCBPrimeConverter.json +218 -0
  146. package/deployments/bscmainnet/ConverterNetwork.json +723 -0
  147. package/deployments/bscmainnet/ConverterNetwork_Implementation.json +823 -0
  148. package/deployments/bscmainnet/ConverterNetwork_Proxy.json +277 -0
  149. package/deployments/bscmainnet/ETHPrimeConverter.json +218 -0
  150. package/deployments/bscmainnet/ProtocolShareReserve_Implementation.json +89 -73
  151. package/deployments/bscmainnet/RiskFundConverter.json +2035 -0
  152. package/deployments/bscmainnet/RiskFundConverter_Implementation.json +2563 -0
  153. package/deployments/bscmainnet/RiskFundConverter_Proxy.json +403 -0
  154. package/deployments/bscmainnet/RiskFundV2.json +1049 -0
  155. package/deployments/bscmainnet/SingleTokenConverterBeacon.json +206 -0
  156. package/deployments/bscmainnet/SingleTokenConverterImp.json +2164 -0
  157. package/deployments/bscmainnet/USDCPrimeConverter.json +218 -0
  158. package/deployments/bscmainnet/USDTPrimeConverter.json +218 -0
  159. package/deployments/bscmainnet/XVSVaultConverter.json +218 -0
  160. package/deployments/bscmainnet/XVSVaultTreasury.json +579 -0
  161. package/deployments/bscmainnet/XVSVaultTreasury_Implementation.json +603 -0
  162. package/deployments/bscmainnet/XVSVaultTreasury_Proxy.json +281 -0
  163. package/deployments/bscmainnet/solcInputs/d02e743d886d63634298edb2c3d7a019.json +123 -0
  164. package/deployments/bscmainnet/solcInputs/ee8827a99e03cdf6f6a94fb8782ddf44.json +228 -0
  165. package/deployments/bscmainnet.json +8927 -873
  166. package/deployments/bscmainnet_addresses.json +19 -2
  167. package/deployments/bsctestnet/BTCBPrimeConverter.json +218 -0
  168. package/deployments/bsctestnet/ConverterNetwork.json +723 -0
  169. package/deployments/bsctestnet/ConverterNetwork_Implementation.json +823 -0
  170. package/deployments/bsctestnet/ConverterNetwork_Proxy.json +277 -0
  171. package/deployments/bsctestnet/ETHPrimeConverter.json +218 -0
  172. package/deployments/bsctestnet/ProtocolShareReserve_Implementation.json +89 -73
  173. package/deployments/bsctestnet/RiskFundConverter.json +2035 -0
  174. package/deployments/bsctestnet/RiskFundConverter_Implementation.json +2563 -0
  175. package/deployments/bsctestnet/RiskFundConverter_Proxy.json +403 -0
  176. package/deployments/bsctestnet/RiskFundV2.json +1049 -0
  177. package/deployments/bsctestnet/SingleTokenConverterBeacon.json +206 -0
  178. package/deployments/bsctestnet/SingleTokenConverterImp.json +2164 -0
  179. package/deployments/bsctestnet/USDCPrimeConverter.json +218 -0
  180. package/deployments/bsctestnet/USDTPrimeConverter.json +218 -0
  181. package/deployments/bsctestnet/XVSVaultConverter.json +218 -0
  182. package/deployments/bsctestnet/XVSVaultTreasury.json +579 -0
  183. package/deployments/bsctestnet/XVSVaultTreasury_Implementation.json +603 -0
  184. package/deployments/bsctestnet/XVSVaultTreasury_Proxy.json +281 -0
  185. package/deployments/bsctestnet/solcInputs/d02e743d886d63634298edb2c3d7a019.json +123 -0
  186. package/deployments/bsctestnet/solcInputs/ee8827a99e03cdf6f6a94fb8782ddf44.json +228 -0
  187. package/deployments/bsctestnet.json +8927 -873
  188. package/deployments/bsctestnet_addresses.json +19 -2
  189. package/dist/deploy/{1-deploy.d.ts → 001-psr.d.ts} +1 -1
  190. package/dist/deploy/001-psr.d.ts.map +1 -0
  191. package/dist/deploy/{1-deploy.js → 001-psr.js} +2 -2
  192. package/dist/deploy/001-psr.js.map +1 -0
  193. package/dist/deploy/002-risk-fund-converter.d.ts +4 -0
  194. package/dist/deploy/002-risk-fund-converter.d.ts.map +1 -0
  195. package/dist/deploy/002-risk-fund-converter.js +78 -0
  196. package/dist/deploy/002-risk-fund-converter.js.map +1 -0
  197. package/dist/deploy/003-xvs-vault-teasury.d.ts +2 -0
  198. package/dist/deploy/003-xvs-vault-teasury.d.ts.map +1 -0
  199. package/dist/deploy/003-xvs-vault-teasury.js +44 -0
  200. package/dist/deploy/003-xvs-vault-teasury.js.map +1 -0
  201. package/dist/deploy/004-single-token-converter.d.ts +4 -0
  202. package/dist/deploy/004-single-token-converter.d.ts.map +1 -0
  203. package/dist/deploy/004-single-token-converter.js +65 -0
  204. package/dist/deploy/004-single-token-converter.js.map +1 -0
  205. package/dist/deploy/005-converter-network.d.ts +2 -0
  206. package/dist/deploy/005-converter-network.d.ts.map +1 -0
  207. package/dist/deploy/005-converter-network.js +42 -0
  208. package/dist/deploy/005-converter-network.js.map +1 -0
  209. package/dist/hardhat.config.d.ts.map +1 -1
  210. package/dist/hardhat.config.js +6 -0
  211. package/dist/hardhat.config.js.map +1 -1
  212. package/dist/helpers/utils.d.ts +1 -0
  213. package/dist/helpers/utils.d.ts.map +1 -1
  214. package/dist/helpers/utils.js +2 -1
  215. package/dist/helpers/utils.js.map +1 -1
  216. package/package.json +19 -16
  217. package/typechain/AbstractTokenConverter.d.ts +1775 -0
  218. package/typechain/AccessControl.d.ts +388 -0
  219. package/typechain/BeaconProxy.d.ts +126 -0
  220. package/typechain/BoundValidatorInterface.d.ts +126 -0
  221. package/typechain/ConverterNetwork.d.ts +723 -0
  222. package/typechain/{PoolRegistryInterface.d.ts → ERC165.d.ts} +20 -25
  223. package/typechain/ERC1967Upgrade.d.ts +126 -0
  224. package/typechain/IAbstractTokenConverter.d.ts +773 -0
  225. package/typechain/IBeacon.d.ts +101 -0
  226. package/typechain/IComptroller.d.ts +136 -0
  227. package/typechain/IConverterNetwork.d.ts +292 -0
  228. package/typechain/IERC165.d.ts +116 -0
  229. package/typechain/{ComptrollerInterface.d.ts → IERC1822Proxiable.d.ts} +11 -11
  230. package/typechain/IERC1967.d.ts +126 -0
  231. package/typechain/IPoolRegistry.d.ts +155 -0
  232. package/typechain/IRiskFund.d.ts +200 -0
  233. package/typechain/IRiskFundConverter.d.ts +138 -0
  234. package/typechain/IRiskFundGetters.d.ts +103 -0
  235. package/typechain/IShortfall.d.ts +110 -0
  236. package/typechain/IXVSVault.d.ts +95 -0
  237. package/typechain/MaxLoopsLimitHelpersStorage.d.ts +101 -0
  238. package/typechain/MockACM.d.ts +615 -0
  239. package/typechain/MockArraySorter.d.ts +118 -0
  240. package/typechain/MockConverter.d.ts +1969 -0
  241. package/typechain/MockDeflatingToken.d.ts +486 -0
  242. package/typechain/MockRiskFundConverter.d.ts +2479 -0
  243. package/typechain/MockToken.d.ts +36 -0
  244. package/typechain/OracleInterface.d.ts +98 -0
  245. package/typechain/Ownable.d.ts +181 -0
  246. package/typechain/PausableUpgradeable.d.ts +129 -0
  247. package/typechain/Proxy.d.ts +78 -0
  248. package/typechain/ReserveHelpersStorage.d.ts +300 -0
  249. package/typechain/ResilientOracle.d.ts +1034 -0
  250. package/typechain/ResilientOracleInterface.d.ts +192 -0
  251. package/typechain/RiskFundConverter.d.ts +2235 -0
  252. package/typechain/RiskFundV1Storage.d.ts +353 -0
  253. package/typechain/RiskFundV2.d.ts +965 -0
  254. package/typechain/RiskFundV2Storage.d.ts +372 -0
  255. package/typechain/SingleTokenConverter.d.ts +1944 -0
  256. package/typechain/TwapInterface.d.ts +124 -0
  257. package/typechain/UpgradeableBeacon.d.ts +240 -0
  258. package/typechain/VBep20Interface.d.ts +379 -0
  259. package/typechain/XVSVaultTreasury.d.ts +515 -0
  260. package/typechain/factories/AbstractTokenConverter__factory.ts +1297 -0
  261. package/typechain/factories/AccessControl__factory.ts +227 -0
  262. package/typechain/factories/BeaconProxy__factory.ts +133 -0
  263. package/typechain/factories/BoundValidatorInterface__factory.ts +59 -0
  264. package/typechain/factories/ConverterNetwork__factory.ts +502 -0
  265. package/typechain/factories/ERC165__factory.ts +39 -0
  266. package/typechain/factories/ERC1967Upgrade__factory.ts +71 -0
  267. package/typechain/factories/IAbstractTokenConverter__factory.ts +466 -0
  268. package/typechain/factories/IBeacon__factory.ts +36 -0
  269. package/typechain/factories/IComptroller__factory.ts +68 -0
  270. package/typechain/factories/IConverterNetwork__factory.ts +142 -0
  271. package/typechain/factories/{ComptrollerInterface__factory.ts → IERC165__factory.ts} +14 -15
  272. package/typechain/factories/IERC1822Proxiable__factory.ts +39 -0
  273. package/typechain/factories/IERC1967__factory.ts +68 -0
  274. package/typechain/factories/IPoolRegistry__factory.ts +66 -0
  275. package/typechain/factories/{PoolRegistryInterface__factory.ts → IRiskFundConverter__factory.ts} +28 -19
  276. package/typechain/factories/IRiskFundGetters__factory.ts +39 -0
  277. package/typechain/factories/IRiskFund__factory.ts +89 -0
  278. package/typechain/factories/IShortfall__factory.ts +36 -0
  279. package/typechain/factories/IXVSVault__factory.ts +36 -0
  280. package/typechain/factories/MaxLoopsLimitHelpersStorage__factory.ts +75 -0
  281. package/typechain/factories/MockACM__factory.ts +411 -0
  282. package/typechain/factories/MockArraySorter__factory.ts +85 -0
  283. package/typechain/factories/MockConverter__factory.ts +1439 -0
  284. package/typechain/factories/MockDeflatingToken__factory.ts +389 -0
  285. package/typechain/factories/MockRiskFundConverter__factory.ts +1828 -0
  286. package/typechain/factories/MockToken__factory.ts +19 -1
  287. package/typechain/factories/OracleInterface__factory.ts +45 -0
  288. package/typechain/factories/Ownable__factory.ts +75 -0
  289. package/typechain/factories/PausableUpgradeable__factory.ts +78 -0
  290. package/typechain/factories/ProtocolShareReserve__factory.ts +6 -1
  291. package/typechain/factories/Proxy__factory.ts +28 -0
  292. package/typechain/factories/ReserveHelpersStorage__factory.ts +188 -0
  293. package/typechain/factories/ResilientOracleInterface__factory.ts +94 -0
  294. package/typechain/factories/ResilientOracle__factory.ts +710 -0
  295. package/typechain/factories/RiskFundConverter__factory.ts +1694 -0
  296. package/typechain/factories/RiskFundV1Storage__factory.ts +223 -0
  297. package/typechain/factories/RiskFundV2Storage__factory.ts +236 -0
  298. package/typechain/factories/RiskFundV2__factory.ts +672 -0
  299. package/typechain/factories/SingleTokenConverter__factory.ts +1441 -0
  300. package/typechain/factories/TwapInterface__factory.ts +61 -0
  301. package/typechain/factories/UpgradeableBeacon__factory.ts +163 -0
  302. package/typechain/factories/VBep20Interface__factory.ts +261 -0
  303. package/typechain/factories/XVSVaultTreasury__factory.ts +365 -0
  304. package/typechain/index.ts +84 -4
  305. package/artifacts/build-info/ac790619cb42a0f08af77d9ea733874e.json +0 -1
  306. package/artifacts/contracts/Interfaces/ComptrollerInterface.sol/ComptrollerInterface.dbg.json +0 -4
  307. package/artifacts/contracts/Interfaces/PoolRegistryInterface.sol/PoolRegistryInterface.dbg.json +0 -4
  308. package/contracts/Interfaces/ComptrollerInterface.sol +0 -6
  309. package/contracts/Interfaces/PoolRegistryInterface.sol +0 -7
  310. package/dist/deploy/1-deploy.d.ts.map +0 -1
  311. package/dist/deploy/1-deploy.js.map +0 -1
@@ -0,0 +1,1167 @@
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
+ import { ensureNonzeroAddress, ensureNonzeroValue } from "@venusprotocol/solidity-utilities/contracts/validators.sol";
10
+ import { MANTISSA_ONE, EXP_SCALE } from "@venusprotocol/solidity-utilities/contracts/constants.sol";
11
+
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 Min amount to convert for private conversions. Defined in USD, with 18 decimals
105
+ uint256 public minAmountToConvert;
106
+
107
+ /// @notice Venus price oracle contract
108
+ ResilientOracle public priceOracle;
109
+
110
+ /// @notice conversion configurations for the existing pairs
111
+ /// @dev tokenAddressIn => tokenAddressOut => ConversionConfig
112
+ mapping(address => mapping(address => ConversionConfig)) public conversionConfigurations;
113
+
114
+ /// @notice Address that all incoming tokens are transferred to
115
+ address public destinationAddress;
116
+
117
+ /// @notice Boolean for if conversion is paused
118
+ bool public conversionPaused;
119
+
120
+ /// @notice Address of the converterNetwork contract
121
+ IConverterNetwork public converterNetwork;
122
+
123
+ /// @dev This empty reserved space is put in place to allow future versions to add new
124
+ /// variables without shifting down storage in the inheritance chain.
125
+ /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
126
+ uint256[45] private __gap;
127
+
128
+ /// @notice Emitted when config is updated for tokens pair
129
+ event ConversionConfigUpdated(
130
+ address indexed tokenAddressIn,
131
+ address indexed tokenAddressOut,
132
+ uint256 oldIncentive,
133
+ uint256 newIncentive,
134
+ ConversionAccessibility oldAccess,
135
+ ConversionAccessibility newAccess
136
+ );
137
+ /// @notice Emitted when price oracle address is updated
138
+ event PriceOracleUpdated(ResilientOracle indexed oldPriceOracle, ResilientOracle indexed priceOracle);
139
+
140
+ /// @notice Emitted when destination address is updated
141
+ event DestinationAddressUpdated(address indexed oldDestinationAddress, address indexed destinationAddress);
142
+
143
+ /// @notice Emitted when converterNetwork address is updated
144
+ event ConverterNetworkAddressUpdated(address indexed oldConverterNetwork, address indexed converterNetwork);
145
+
146
+ /// @notice Emitted when exact amount of tokens are converted for tokens
147
+ event ConvertedExactTokens(
148
+ address indexed sender,
149
+ address indexed receiver,
150
+ address tokenAddressIn,
151
+ address indexed tokenAddressOut,
152
+ uint256 amountIn,
153
+ uint256 amountOut
154
+ );
155
+
156
+ /// @notice Emitted when tokens are converted for exact amount of tokens
157
+ event ConvertedForExactTokens(
158
+ address indexed sender,
159
+ address indexed receiver,
160
+ address tokenAddressIn,
161
+ address indexed tokenAddressOut,
162
+ uint256 amountIn,
163
+ uint256 amountOut
164
+ );
165
+
166
+ /// @notice Emitted when exact amount of tokens are converted for tokens, for deflationary tokens
167
+ event ConvertedExactTokensSupportingFeeOnTransferTokens(
168
+ address indexed sender,
169
+ address indexed receiver,
170
+ address tokenAddressIn,
171
+ address indexed tokenAddressOut,
172
+ uint256 amountIn,
173
+ uint256 amountOut
174
+ );
175
+
176
+ /// @notice Emitted when tokens are converted for exact amount of tokens, for deflationary tokens
177
+ event ConvertedForExactTokensSupportingFeeOnTransferTokens(
178
+ address indexed sender,
179
+ address indexed receiver,
180
+ address tokenAddressIn,
181
+ address indexed tokenAddressOut,
182
+ uint256 amountIn,
183
+ uint256 amountOut
184
+ );
185
+
186
+ /// @notice Emitted when conversion is paused
187
+ event ConversionPaused(address indexed sender);
188
+
189
+ /// @notice Emitted when conversion is unpaused
190
+ event ConversionResumed(address indexed sender);
191
+
192
+ /// @notice Event emitted when tokens are swept
193
+ event SweepToken(address indexed token, address indexed to, uint256 amount);
194
+
195
+ /// @notice Emitted when minimum amount to convert is updated
196
+ event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);
197
+
198
+ /// @notice Thrown when actualAmountOut does not match with amountOutMantissa for convertForExactTokens
199
+ error AmountOutMismatched();
200
+
201
+ /// @notice Thrown when actualAmountIn does not match with amountInMantissa for convertForExactTokens
202
+ error AmountInMismatched();
203
+
204
+ /// @notice Thrown when given input amount is zero
205
+ error InsufficientInputAmount();
206
+
207
+ /// @notice Thrown when given output amount is zero
208
+ error InsufficientOutputAmount();
209
+
210
+ /// @notice Thrown when conversion is disabled or config does not exist for given pair
211
+ error ConversionConfigNotEnabled();
212
+
213
+ /// @notice Thrown when conversion is enabled only for private conversions
214
+ error ConversionEnabledOnlyForPrivateConversions();
215
+
216
+ /// @notice Thrown when address(to) is same as tokenAddressIn or tokenAddressOut
217
+ error InvalidToAddress();
218
+
219
+ /// @notice Thrown when incentive is higher than the MAX_INCENTIVE
220
+ error IncentiveTooHigh(uint256 incentive, uint256 maxIncentive);
221
+
222
+ /// @notice Thrown when amountOut is lower than amountOutMin
223
+ error AmountOutLowerThanMinRequired(uint256 amountOutMantissa, uint256 amountOutMinMantissa);
224
+
225
+ /// @notice Thrown when amountIn is higher than amountInMax
226
+ error AmountInHigherThanMax(uint256 amountInMantissa, uint256 amountInMaxMantissa);
227
+
228
+ /// @notice Thrown when conversion is paused
229
+ error ConversionTokensPaused();
230
+
231
+ /// @notice Thrown when conversion is Active
232
+ error ConversionTokensActive();
233
+
234
+ /// @notice Thrown when tokenInAddress is same as tokeOutAdress OR tokeInAddress is not the base asset of the destination
235
+ error InvalidTokenConfigAddresses();
236
+
237
+ /// @notice Thrown when contract has less liquidity for tokenAddressOut than amountOutMantissa
238
+ error InsufficientPoolLiquidity();
239
+
240
+ /// @notice When address of the ConverterNetwork is not set or Zero address
241
+ error InvalidConverterNetwork();
242
+
243
+ /// @notice Thrown when trying to set non zero incentive for private conversion
244
+ error NonZeroIncentiveForPrivateConversion();
245
+
246
+ /// @notice Thrown when using convertForExactTokens deflationary tokens
247
+ error DeflationaryTokenNotSupported();
248
+
249
+ /// @notice Thrown when minimum amount to convert is zero
250
+ error InvalidMinimumAmountToConvert();
251
+
252
+ /// @notice Thrown when there is a mismatch in the length of input arrays
253
+ error InputLengthMisMatch();
254
+
255
+ /**
256
+ * @notice Modifier to ensure valid conversion parameters for a token conversion
257
+ * and check if conversion is paused or not
258
+ * @param to The recipient address for the converted tokens
259
+ * @param tokenAddressIn The input token address for the conversion
260
+ * @param tokenAddressOut The output token address for the conversion
261
+ */
262
+ modifier validConversionParameters(
263
+ address to,
264
+ address tokenAddressIn,
265
+ address tokenAddressOut
266
+ ) {
267
+ _checkConversionPaused();
268
+ ensureNonzeroAddress(to);
269
+ if (to == tokenAddressIn || to == tokenAddressOut) {
270
+ revert InvalidToAddress();
271
+ }
272
+ _;
273
+ }
274
+
275
+ /// @notice Pause conversion of tokens
276
+ /// @custom:event Emits ConversionPaused on success
277
+ /// @custom:error ConversionTokensPaused thrown when conversion is already paused
278
+ /// @custom:access Restricted by ACM
279
+ function pauseConversion() external {
280
+ _checkAccessAllowed("pauseConversion()");
281
+ _checkConversionPaused();
282
+ conversionPaused = true;
283
+ emit ConversionPaused(msg.sender);
284
+ }
285
+
286
+ /// @notice Resume conversion of tokens.
287
+ /// @custom:event Emits ConversionResumed on success
288
+ /// @custom:error ConversionTokensActive thrown when conversion is already active
289
+ /// @custom:access Restricted by ACM
290
+ function resumeConversion() external {
291
+ _checkAccessAllowed("resumeConversion()");
292
+ if (!conversionPaused) {
293
+ revert ConversionTokensActive();
294
+ }
295
+
296
+ conversionPaused = false;
297
+ emit ConversionResumed(msg.sender);
298
+ }
299
+
300
+ /// @notice Sets a new price oracle
301
+ /// @param priceOracle_ Address of the new price oracle to set
302
+ /// @custom:access Only Governance
303
+ function setPriceOracle(ResilientOracle priceOracle_) external onlyOwner {
304
+ _setPriceOracle(priceOracle_);
305
+ }
306
+
307
+ /// @notice Sets a new destination address
308
+ /// @param destinationAddress_ The new destination address to be set
309
+ /// @custom:access Only Governance
310
+ function setDestination(address destinationAddress_) external onlyOwner {
311
+ _setDestination(destinationAddress_);
312
+ }
313
+
314
+ /// @notice Sets a converter network contract address
315
+ /// @param converterNetwork_ The converterNetwork address to be set
316
+ /// @custom:access Only Governance
317
+ function setConverterNetwork(IConverterNetwork converterNetwork_) external onlyOwner {
318
+ _setConverterNetwork(converterNetwork_);
319
+ }
320
+
321
+ /// @notice Min amount to convert setter
322
+ /// @param minAmountToConvert_ Min amount to convert
323
+ /// @custom:access Only Governance
324
+ function setMinAmountToConvert(uint256 minAmountToConvert_) external {
325
+ _checkAccessAllowed("setMinAmountToConvert(uint256)");
326
+ _setMinAmountToConvert(minAmountToConvert_);
327
+ }
328
+
329
+ /// @notice Batch sets the conversion configurations
330
+ /// @param tokenAddressIn Address of tokenIn
331
+ /// @param tokenAddressesOut Array of addresses of tokenOut
332
+ /// @param conversionConfigs Array of conversionConfig config details to update
333
+ /// @custom:error InputLengthMisMatch is thrown when tokenAddressesOut and conversionConfigs array length mismatches
334
+ function setConversionConfigs(
335
+ address tokenAddressIn,
336
+ address[] calldata tokenAddressesOut,
337
+ ConversionConfig[] calldata conversionConfigs
338
+ ) external {
339
+ uint256 tokenOutArrayLength = tokenAddressesOut.length;
340
+ if (tokenOutArrayLength != conversionConfigs.length) revert InputLengthMisMatch();
341
+
342
+ for (uint256 i; i < tokenOutArrayLength; ) {
343
+ setConversionConfig(tokenAddressIn, tokenAddressesOut[i], conversionConfigs[i]);
344
+ unchecked {
345
+ ++i;
346
+ }
347
+ }
348
+ }
349
+
350
+ /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract
351
+ /// @dev Method does not support deflationary tokens transfer
352
+ /// @param amountInMantissa Amount of tokenAddressIn
353
+ /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output
354
+ /// @param tokenAddressIn Address of the token to convert
355
+ /// @param tokenAddressOut Address of the token to get after conversion
356
+ /// @param to Address of the tokenAddressOut receiver
357
+ /// @return actualAmountIn Actual amount transferred to destination
358
+ /// @return actualAmountOut Actual amount transferred to user
359
+ /// @custom:event Emits ConvertedExactTokens event on success
360
+ /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero
361
+ /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut
362
+ /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa
363
+ /// @custom:error AmountInMismatched error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa
364
+ function convertExactTokens(
365
+ uint256 amountInMantissa,
366
+ uint256 amountOutMinMantissa,
367
+ address tokenAddressIn,
368
+ address tokenAddressOut,
369
+ address to
370
+ )
371
+ external
372
+ validConversionParameters(to, tokenAddressIn, tokenAddressOut)
373
+ nonReentrant
374
+ returns (uint256 actualAmountIn, uint256 actualAmountOut)
375
+ {
376
+ (actualAmountIn, actualAmountOut) = _convertExactTokens(
377
+ amountInMantissa,
378
+ amountOutMinMantissa,
379
+ tokenAddressIn,
380
+ tokenAddressOut,
381
+ to
382
+ );
383
+
384
+ if (actualAmountIn != amountInMantissa) {
385
+ revert AmountInMismatched();
386
+ }
387
+
388
+ _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);
389
+ emit ConvertedExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);
390
+ }
391
+
392
+ /// @notice Converts tokens for tokenAddressIn for exact amount of tokenAddressOut if there is enough tokens held by the contract,
393
+ /// otherwise the amount is adjusted
394
+ /// @dev Method does not support deflationary tokens transfer
395
+ /// @param amountInMaxMantissa Max amount of tokenAddressIn
396
+ /// @param amountOutMantissa Amount of tokenAddressOut required as output
397
+ /// @param tokenAddressIn Address of the token to convert
398
+ /// @param tokenAddressOut Address of the token to get after conversion
399
+ /// @param to Address of the tokenAddressOut receiver
400
+ /// @return actualAmountIn Actual amount transferred to destination
401
+ /// @return actualAmountOut Actual amount transferred to user
402
+ /// @custom:event Emits ConvertedForExactTokens event on success
403
+ /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero
404
+ /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut
405
+ /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa
406
+ /// @custom:error AmountOutMismatched error is thrown when actualAmountOut is does not match amountOutMantissa
407
+ function convertForExactTokens(
408
+ uint256 amountInMaxMantissa,
409
+ uint256 amountOutMantissa,
410
+ address tokenAddressIn,
411
+ address tokenAddressOut,
412
+ address to
413
+ )
414
+ external
415
+ validConversionParameters(to, tokenAddressIn, tokenAddressOut)
416
+ nonReentrant
417
+ returns (uint256 actualAmountIn, uint256 actualAmountOut)
418
+ {
419
+ (actualAmountIn, actualAmountOut) = _convertForExactTokens(
420
+ amountInMaxMantissa,
421
+ amountOutMantissa,
422
+ tokenAddressIn,
423
+ tokenAddressOut,
424
+ to
425
+ );
426
+
427
+ if (actualAmountOut != amountOutMantissa) {
428
+ revert AmountOutMismatched();
429
+ }
430
+
431
+ _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);
432
+ emit ConvertedForExactTokens(msg.sender, to, tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);
433
+ }
434
+
435
+ /// @notice Converts exact amount of tokenAddressIn for tokenAddressOut if there is enough tokens held by the contract
436
+ /// @param amountInMantissa Amount of tokenAddressIn
437
+ /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output
438
+ /// @param tokenAddressIn Address of the token to convert
439
+ /// @param tokenAddressOut Address of the token to get after conversion
440
+ /// @param to Address of the tokenAddressOut receiver
441
+ /// @return actualAmountIn Actual amount transferred to destination
442
+ /// @return actualAmountOut Actual amount transferred to user
443
+ /// @custom:event Emits ConvertedExactTokensSupportingFeeOnTransferTokens event on success
444
+ /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero
445
+ /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut
446
+ /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa
447
+ function convertExactTokensSupportingFeeOnTransferTokens(
448
+ uint256 amountInMantissa,
449
+ uint256 amountOutMinMantissa,
450
+ address tokenAddressIn,
451
+ address tokenAddressOut,
452
+ address to
453
+ )
454
+ external
455
+ validConversionParameters(to, tokenAddressIn, tokenAddressOut)
456
+ nonReentrant
457
+ returns (uint256 actualAmountIn, uint256 actualAmountOut)
458
+ {
459
+ (actualAmountIn, actualAmountOut) = _convertExactTokens(
460
+ amountInMantissa,
461
+ amountOutMinMantissa,
462
+ tokenAddressIn,
463
+ tokenAddressOut,
464
+ to
465
+ );
466
+
467
+ _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);
468
+ emit ConvertedExactTokensSupportingFeeOnTransferTokens(
469
+ msg.sender,
470
+ to,
471
+ tokenAddressIn,
472
+ tokenAddressOut,
473
+ actualAmountIn,
474
+ actualAmountOut
475
+ );
476
+ }
477
+
478
+ /// @notice Converts tokens for tokenAddressIn for amount of tokenAddressOut calculated on the basis of amount of
479
+ /// tokenAddressIn received by the contract, if there is enough tokens held by the contract, otherwise the amount is adjusted.
480
+ /// The user will be responsible for bearing any fees associated with token transfers, whether pulling in or pushing out tokens
481
+ /// @param amountInMaxMantissa Max amount of tokenAddressIn
482
+ /// @param amountOutMantissa Amount of tokenAddressOut required as output
483
+ /// @param tokenAddressIn Address of the token to convert
484
+ /// @param tokenAddressOut Address of the token to get after conversion
485
+ /// @param to Address of the tokenAddressOut receiver
486
+ /// @return actualAmountIn Actual amount transferred to destination
487
+ /// @return actualAmountOut Actual amount transferred to user
488
+ /// @custom:event Emits ConvertedForExactTokensSupportingFeeOnTransferTokens event on success
489
+ /// @custom:error ZeroAddressNotAllowed is thrown when to address is zero
490
+ /// @custom:error InvalidToAddress error is thrown when address(to) is same as tokenAddressIn or tokenAddressOut
491
+ /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa
492
+ function convertForExactTokensSupportingFeeOnTransferTokens(
493
+ uint256 amountInMaxMantissa,
494
+ uint256 amountOutMantissa,
495
+ address tokenAddressIn,
496
+ address tokenAddressOut,
497
+ address to
498
+ )
499
+ external
500
+ validConversionParameters(to, tokenAddressIn, tokenAddressOut)
501
+ nonReentrant
502
+ returns (uint256 actualAmountIn, uint256 actualAmountOut)
503
+ {
504
+ (actualAmountIn, actualAmountOut) = _convertForExactTokensSupportingFeeOnTransferTokens(
505
+ amountInMaxMantissa,
506
+ amountOutMantissa,
507
+ tokenAddressIn,
508
+ tokenAddressOut,
509
+ to
510
+ );
511
+
512
+ _postConversionHook(tokenAddressIn, tokenAddressOut, actualAmountIn, actualAmountOut);
513
+ emit ConvertedForExactTokensSupportingFeeOnTransferTokens(
514
+ msg.sender,
515
+ to,
516
+ tokenAddressIn,
517
+ tokenAddressOut,
518
+ actualAmountIn,
519
+ actualAmountOut
520
+ );
521
+ }
522
+
523
+ /// @notice To sweep ERC20 tokens and transfer them to user(to address)
524
+ /// @param tokenAddress The address of the ERC-20 token to sweep
525
+ /// @param to The address to which tokens will be transferred
526
+ /// @param amount The amount to transfer
527
+ /// @custom:event Emits SweepToken event on success
528
+ /// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero
529
+ /// @custom:access Only Governance
530
+ function sweepToken(
531
+ address tokenAddress,
532
+ address to,
533
+ uint256 amount
534
+ ) external onlyOwner nonReentrant {
535
+ ensureNonzeroAddress(tokenAddress);
536
+ ensureNonzeroAddress(to);
537
+ ensureNonzeroValue(amount);
538
+
539
+ IERC20Upgradeable token = IERC20Upgradeable(tokenAddress);
540
+ preSweepToken(tokenAddress, amount);
541
+ token.safeTransfer(to, amount);
542
+
543
+ emit SweepToken(tokenAddress, to, amount);
544
+ }
545
+
546
+ /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn.
547
+ /// This function does not account for potential token transfer fees(in case of deflationary tokens)
548
+ /// @dev This function retrieves values without altering token prices
549
+ /// @param amountInMantissa Amount of tokenAddressIn
550
+ /// @param tokenAddressIn Address of the token to convert
551
+ /// @param tokenAddressOut Address of the token to get after conversion
552
+ /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion
553
+ /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion
554
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
555
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
556
+ /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion
557
+ function getAmountOut(
558
+ uint256 amountInMantissa,
559
+ address tokenAddressIn,
560
+ address tokenAddressOut
561
+ ) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {
562
+ if (
563
+ conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==
564
+ ConversionAccessibility.ONLY_FOR_CONVERTERS
565
+ ) {
566
+ revert ConversionEnabledOnlyForPrivateConversions();
567
+ }
568
+
569
+ amountConvertedMantissa = amountInMantissa;
570
+ uint256 tokenInToOutConversion;
571
+ (amountOutMantissa, tokenInToOutConversion) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);
572
+
573
+ uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);
574
+
575
+ /// If contract has less liquidity for tokenAddressOut than amountOutMantissa
576
+ if (maxTokenOutReserve < amountOutMantissa) {
577
+ amountConvertedMantissa =
578
+ ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) /
579
+ tokenInToOutConversion; //round-up
580
+ amountOutMantissa = maxTokenOutReserve;
581
+ }
582
+ }
583
+
584
+ /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut.
585
+ /// This function does not account for potential token transfer fees(in case of deflationary tokens)
586
+ /// @dev This function retrieves values without altering token prices
587
+ /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive
588
+ /// @param tokenAddressIn Address of the token to convert
589
+ /// @param tokenAddressOut Address of the token to get after conversion
590
+ /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion
591
+ /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion
592
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
593
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
594
+ /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion
595
+ function getAmountIn(
596
+ uint256 amountOutMantissa,
597
+ address tokenAddressIn,
598
+ address tokenAddressOut
599
+ ) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {
600
+ if (
601
+ conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==
602
+ ConversionAccessibility.ONLY_FOR_CONVERTERS
603
+ ) {
604
+ revert ConversionEnabledOnlyForPrivateConversions();
605
+ }
606
+
607
+ uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);
608
+
609
+ /// If contract has less liquidity for tokenAddressOut than amountOutMantissa
610
+ if (maxTokenOutReserve < amountOutMantissa) {
611
+ amountOutMantissa = maxTokenOutReserve;
612
+ }
613
+
614
+ amountConvertedMantissa = amountOutMantissa;
615
+ (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);
616
+ }
617
+
618
+ /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn
619
+ /// @param amountInMantissa Amount of tokenAddressIn
620
+ /// @param tokenAddressIn Address of the token to convert
621
+ /// @param tokenAddressOut Address of the token to get after conversion
622
+ /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion
623
+ /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion
624
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
625
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
626
+ function getUpdatedAmountOut(
627
+ uint256 amountInMantissa,
628
+ address tokenAddressIn,
629
+ address tokenAddressOut
630
+ ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {
631
+ priceOracle.updateAssetPrice(tokenAddressIn);
632
+ priceOracle.updateAssetPrice(tokenAddressOut);
633
+
634
+ (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);
635
+ amountConvertedMantissa = amountInMantissa;
636
+ }
637
+
638
+ /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut
639
+ /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive
640
+ /// @param tokenAddressIn Address of the token to convert
641
+ /// @param tokenAddressOut Address of the token to get after conversion
642
+ /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion
643
+ /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion
644
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
645
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
646
+ function getUpdatedAmountIn(
647
+ uint256 amountOutMantissa,
648
+ address tokenAddressIn,
649
+ address tokenAddressOut
650
+ ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {
651
+ priceOracle.updateAssetPrice(tokenAddressIn);
652
+ priceOracle.updateAssetPrice(tokenAddressOut);
653
+
654
+ (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);
655
+ amountConvertedMantissa = amountOutMantissa;
656
+ }
657
+
658
+ /// @notice This method updated the states of this contract after getting funds from PSR
659
+ /// after settling the amount(if any) through privateConversion between converters
660
+ /// @dev This function is called by protocolShareReserve
661
+ /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then
662
+ /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address
663
+ /// @param comptroller Comptroller address (pool)
664
+ /// @param asset Asset address
665
+ function updateAssetsState(address comptroller, address asset) public nonReentrant {
666
+ uint256 balanceDiff = _updateAssetsState(comptroller, asset);
667
+ if (balanceDiff > 0) {
668
+ _privateConversion(comptroller, asset, balanceDiff);
669
+ }
670
+ }
671
+
672
+ /// @notice Set the configuration for new or existing conversion pair
673
+ /// @param tokenAddressIn Address of tokenIn
674
+ /// @param tokenAddressOut Address of tokenOut
675
+ /// @param conversionConfig ConversionConfig config details to update
676
+ /// @custom:event Emits ConversionConfigUpdated event on success
677
+ /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager
678
+ /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero
679
+ /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion
680
+ /// @custom:access Controlled by AccessControlManager
681
+ function setConversionConfig(
682
+ address tokenAddressIn,
683
+ address tokenAddressOut,
684
+ ConversionConfig calldata conversionConfig
685
+ ) public {
686
+ _checkAccessAllowed("setConversionConfig(address,address,ConversionConfig)");
687
+ ensureNonzeroAddress(tokenAddressIn);
688
+ ensureNonzeroAddress(tokenAddressOut);
689
+
690
+ if (conversionConfig.incentive > MAX_INCENTIVE) {
691
+ revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);
692
+ }
693
+
694
+ if (
695
+ (tokenAddressIn == tokenAddressOut) ||
696
+ (tokenAddressIn != _getDestinationBaseAsset()) ||
697
+ conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE
698
+ ) {
699
+ revert InvalidTokenConfigAddresses();
700
+ }
701
+
702
+ if (
703
+ (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&
704
+ conversionConfig.incentive != 0
705
+ ) {
706
+ revert NonZeroIncentiveForPrivateConversion();
707
+ }
708
+
709
+ if (
710
+ ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||
711
+ (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&
712
+ (address(converterNetwork) == address(0))
713
+ ) {
714
+ revert InvalidConverterNetwork();
715
+ }
716
+
717
+ ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];
718
+
719
+ emit ConversionConfigUpdated(
720
+ tokenAddressIn,
721
+ tokenAddressOut,
722
+ configuration.incentive,
723
+ conversionConfig.incentive,
724
+ configuration.conversionAccess,
725
+ conversionConfig.conversionAccess
726
+ );
727
+
728
+ if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {
729
+ delete conversionConfigurations[tokenAddressIn][tokenAddressOut];
730
+ } else {
731
+ configuration.incentive = conversionConfig.incentive;
732
+ configuration.conversionAccess = conversionConfig.conversionAccess;
733
+ }
734
+ }
735
+
736
+ /// @notice Get the balance for specific token
737
+ /// @param token Address of the token
738
+ /// @return tokenBalance Balance of the token the contract has
739
+ function balanceOf(address token) public view virtual returns (uint256 tokenBalance);
740
+
741
+ /// @dev Operations to perform before sweeping tokens
742
+ /// @param token Address of the token
743
+ /// @param amount Amount transferred to address(to)
744
+ function preSweepToken(address token, uint256 amount) internal virtual {}
745
+
746
+ /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut
747
+ /// @param amountInMantissa Amount of tokenAddressIn
748
+ /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output
749
+ /// @param tokenAddressIn Address of the token to convert
750
+ /// @param tokenAddressOut Address of the token to get after conversion
751
+ /// @param to Address of the tokenAddressOut receiver
752
+ /// @return actualAmountIn Actual amount of tokenAddressIn transferred
753
+ /// @return amountOutMantissa Actual amount of tokenAddressOut transferred
754
+ /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa
755
+ function _convertExactTokens(
756
+ uint256 amountInMantissa,
757
+ uint256 amountOutMinMantissa,
758
+ address tokenAddressIn,
759
+ address tokenAddressOut,
760
+ address to
761
+ ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {
762
+ _checkPrivateConversion(tokenAddressIn, tokenAddressOut);
763
+ actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);
764
+
765
+ (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);
766
+
767
+ if (amountOutMantissa < amountOutMinMantissa) {
768
+ revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);
769
+ }
770
+
771
+ _doTransferOut(tokenAddressOut, to, amountOutMantissa);
772
+ }
773
+
774
+ /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens
775
+ /// it is called by convertForExactTokens function
776
+ /// @param amountInMaxMantissa Max amount of tokenAddressIn
777
+ /// @param amountOutMantissa Amount of tokenAddressOut required as output
778
+ /// @param tokenAddressIn Address of the token to convert
779
+ /// @param tokenAddressOut Address of the token to get after conversion
780
+ /// @param to Address of the tokenAddressOut receiver
781
+ /// @return actualAmountIn Actual amount of tokenAddressIn transferred
782
+ /// @return actualAmountOut Actual amount of tokenAddressOut transferred
783
+ /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token
784
+ /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa
785
+ function _convertForExactTokens(
786
+ uint256 amountInMaxMantissa,
787
+ uint256 amountOutMantissa,
788
+ address tokenAddressIn,
789
+ address tokenAddressOut,
790
+ address to
791
+ ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {
792
+ _checkPrivateConversion(tokenAddressIn, tokenAddressOut);
793
+ (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);
794
+
795
+ actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);
796
+
797
+ if (actualAmountIn != amountInMantissa) {
798
+ revert DeflationaryTokenNotSupported();
799
+ }
800
+
801
+ if (actualAmountIn > amountInMaxMantissa) {
802
+ revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);
803
+ }
804
+
805
+ _doTransferOut(tokenAddressOut, to, amountOutMantissa);
806
+ actualAmountOut = amountOutMantissa;
807
+ }
808
+
809
+ /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens
810
+ /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function
811
+ /// @param amountInMaxMantissa Max amount of tokenAddressIn
812
+ /// @param amountOutMantissa Amount of tokenAddressOut required as output
813
+ /// @param tokenAddressIn Address of the token to convert
814
+ /// @param tokenAddressOut Address of the token to get after conversion
815
+ /// @param to Address of the tokenAddressOut receiver
816
+ /// @return actualAmountIn Actual amount of tokenAddressIn transferred
817
+ /// @return actualAmountOut Actual amount of tokenAddressOut transferred
818
+ /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa
819
+ function _convertForExactTokensSupportingFeeOnTransferTokens(
820
+ uint256 amountInMaxMantissa,
821
+ uint256 amountOutMantissa,
822
+ address tokenAddressIn,
823
+ address tokenAddressOut,
824
+ address to
825
+ ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {
826
+ _checkPrivateConversion(tokenAddressIn, tokenAddressOut);
827
+ (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);
828
+
829
+ if (amountInMantissa > amountInMaxMantissa) {
830
+ revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);
831
+ }
832
+
833
+ actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);
834
+
835
+ (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);
836
+
837
+ _doTransferOut(tokenAddressOut, to, actualAmountOut);
838
+ }
839
+
840
+ /// @dev return actualAmountOut from reserves for tokenAddressOut
841
+ /// @param tokenAddressOut Address of the token to get after conversion
842
+ /// @param to Address of the tokenAddressOut receiver
843
+ /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred
844
+ /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa
845
+ function _doTransferOut(
846
+ address tokenAddressOut,
847
+ address to,
848
+ uint256 amountConvertedMantissa
849
+ ) internal {
850
+ uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);
851
+
852
+ /// If contract has less liquidity for tokenAddressOut than amountOutMantissa
853
+ if (maxTokenOutReserve < amountConvertedMantissa) {
854
+ revert InsufficientPoolLiquidity();
855
+ }
856
+
857
+ _preTransferHook(tokenAddressOut, amountConvertedMantissa);
858
+
859
+ IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);
860
+ tokenOut.safeTransfer(to, amountConvertedMantissa);
861
+ }
862
+
863
+ /// @notice Transfer tokenAddressIn from user to destination
864
+ /// @param tokenAddressIn Address of the token to convert
865
+ /// @param amountInMantissa Amount of tokenAddressIn
866
+ /// @return actualAmountIn Actual amount transferred to destination
867
+ function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {
868
+ IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);
869
+ uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);
870
+ tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);
871
+ uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);
872
+ actualAmountIn = balanceAfterDestination - balanceBeforeDestination;
873
+ }
874
+
875
+ /// @dev Sets a new price oracle
876
+ /// @param priceOracle_ Address of the new price oracle to set
877
+ /// @custom:event Emits PriceOracleUpdated event on success
878
+ /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero
879
+ function _setPriceOracle(ResilientOracle priceOracle_) internal {
880
+ ensureNonzeroAddress(address(priceOracle_));
881
+ emit PriceOracleUpdated(priceOracle, priceOracle_);
882
+ priceOracle = priceOracle_;
883
+ }
884
+
885
+ /// @dev Sets a new destination address
886
+ /// @param destinationAddress_ The new destination address to be set
887
+ /// @custom:event Emits DestinationAddressUpdated event on success
888
+ /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero
889
+ function _setDestination(address destinationAddress_) internal {
890
+ ensureNonzeroAddress(destinationAddress_);
891
+ emit DestinationAddressUpdated(destinationAddress, destinationAddress_);
892
+ destinationAddress = destinationAddress_;
893
+ }
894
+
895
+ /// @notice Sets a converter network contract address
896
+ /// @param converterNetwork_ The converterNetwork address to be set
897
+ /// @custom:event Emits ConverterNetworkAddressUpdated event on success
898
+ /// @custom:error ZeroAddressNotAllowed is thrown when address is zero
899
+ function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {
900
+ ensureNonzeroAddress(address(converterNetwork_));
901
+ emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));
902
+ converterNetwork = converterNetwork_;
903
+ }
904
+
905
+ /// @notice Min amount to convert setter
906
+ /// @param minAmountToConvert_ Min amount to convert
907
+ /// @custom:event MinAmountToConvertUpdated is emitted in success
908
+ /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0
909
+ function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {
910
+ ensureNonzeroValue(minAmountToConvert_);
911
+ emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);
912
+ minAmountToConvert = minAmountToConvert_;
913
+ }
914
+
915
+ /// @dev Hook to perform after converting tokens
916
+ /// @param tokenAddressIn Address of the token to convert
917
+ /// @param tokenAddressOut Address of the token to get after conversion
918
+ /// @param amountIn Amount of tokenIn converted
919
+ /// @param amountOut Amount of tokenOut converted
920
+ function _postConversionHook(
921
+ address tokenAddressIn,
922
+ address tokenAddressOut,
923
+ uint256 amountIn,
924
+ uint256 amountOut
925
+ ) internal virtual {}
926
+
927
+ /// @param accessControlManager_ Access control manager contract address
928
+ /// @param priceOracle_ Resilient oracle address
929
+ /// @param destinationAddress_ Address at all incoming tokens will transferred to
930
+ /// @param minAmountToConvert_ minimum amount to convert
931
+ function __AbstractTokenConverter_init(
932
+ address accessControlManager_,
933
+ ResilientOracle priceOracle_,
934
+ address destinationAddress_,
935
+ uint256 minAmountToConvert_
936
+ ) internal onlyInitializing {
937
+ __AccessControlled_init(accessControlManager_);
938
+ __ReentrancyGuard_init();
939
+ __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);
940
+ }
941
+
942
+ /// @param priceOracle_ Resilient oracle address
943
+ /// @param destinationAddress_ Address at all incoming tokens will transferred to
944
+ /// @param minAmountToConvert_ minimum amount to convert
945
+ function __AbstractTokenConverter_init_unchained(
946
+ ResilientOracle priceOracle_,
947
+ address destinationAddress_,
948
+ uint256 minAmountToConvert_
949
+ ) internal onlyInitializing {
950
+ _setPriceOracle(priceOracle_);
951
+ _setDestination(destinationAddress_);
952
+ _setMinAmountToConvert(minAmountToConvert_);
953
+ conversionPaused = false;
954
+ }
955
+
956
+ /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller
957
+ /// @param comptroller Comptroller address (pool)
958
+ /// @param asset Asset address
959
+ /// @return Amount of asset, for _privateConversion
960
+ function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}
961
+
962
+ /// @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
963
+ /// destination contract as destination's base asset
964
+ /// @param comptroller Comptroller address (pool)
965
+ /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset
966
+ /// @param amountToConvert Amount of the tokenAddressOut transferred to converter
967
+ function _privateConversion(
968
+ address comptroller,
969
+ address tokenAddressOut,
970
+ uint256 amountToConvert
971
+ ) internal {
972
+ address tokenAddressIn = _getDestinationBaseAsset();
973
+ address _destinationAddress = destinationAddress;
974
+ uint256 convertedTokenInBalance;
975
+ if (address(converterNetwork) != address(0)) {
976
+ (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork
977
+ .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);
978
+ uint256 convertersLength = converterAddresses.length;
979
+ for (uint256 i; i < convertersLength; ) {
980
+ if (converterBalances[i] == 0) break;
981
+ (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(
982
+ converterBalances[i],
983
+ tokenAddressOut,
984
+ tokenAddressIn
985
+ );
986
+ if (amountIn > amountToConvert) {
987
+ amountIn = amountToConvert;
988
+ }
989
+
990
+ if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {
991
+ break;
992
+ }
993
+
994
+ uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);
995
+
996
+ IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);
997
+ IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(
998
+ amountIn,
999
+ 0,
1000
+ tokenAddressOut,
1001
+ tokenAddressIn,
1002
+ _destinationAddress
1003
+ );
1004
+
1005
+ uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);
1006
+ amountToConvert -= amountIn;
1007
+ convertedTokenInBalance += (balanceAfter - balanceBefore);
1008
+
1009
+ if (amountToConvert == 0) break;
1010
+ unchecked {
1011
+ ++i;
1012
+ }
1013
+ }
1014
+ }
1015
+
1016
+ _postPrivateConversionHook(
1017
+ comptroller,
1018
+ tokenAddressIn,
1019
+ convertedTokenInBalance,
1020
+ tokenAddressOut,
1021
+ amountToConvert
1022
+ );
1023
+ }
1024
+
1025
+ /// @dev This hook is used to update states for the converter after the privateConversion
1026
+ /// @param comptroller Comptroller address (pool)
1027
+ /// @param tokenAddressIn Address of the destination's base asset
1028
+ /// @param convertedTokenInBalance Amount of the base asset received after the conversion
1029
+ /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset
1030
+ /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter
1031
+ function _postPrivateConversionHook(
1032
+ address comptroller,
1033
+ address tokenAddressIn,
1034
+ uint256 convertedTokenInBalance,
1035
+ address tokenAddressOut,
1036
+ uint256 convertedTokenOutBalance
1037
+ ) internal virtual {}
1038
+
1039
+ /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user
1040
+ /// @param tokenOutAddress Address of the asset to be transferred to the user
1041
+ /// @param amountOut Amount of tokenAddressOut transferred from this converter
1042
+ function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}
1043
+
1044
+ /// @dev Checks if amount to convert is greater than minimum amount to convert or not
1045
+ /// @param amountIn The amount to convert
1046
+ /// @param tokenAddress Address of the token
1047
+ /// @return isValid true if amount to convert is greater than minimum amount to convert
1048
+ function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {
1049
+ priceOracle.updateAssetPrice(tokenAddress);
1050
+ uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;
1051
+
1052
+ if (amountInInUsd >= minAmountToConvert) {
1053
+ isValid = true;
1054
+ }
1055
+ }
1056
+
1057
+ /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn
1058
+ /// @dev This function retrieves values without altering token prices.
1059
+ /// @param amountInMantissa Amount of tokenAddressIn
1060
+ /// @param tokenAddressIn Address of the token to convert
1061
+ /// @param tokenAddressOut Address of the token to get after conversion
1062
+ /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion
1063
+ /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price
1064
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
1065
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
1066
+ function _getAmountOut(
1067
+ uint256 amountInMantissa,
1068
+ address tokenAddressIn,
1069
+ address tokenAddressOut
1070
+ ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {
1071
+ if (amountInMantissa == 0) {
1072
+ revert InsufficientInputAmount();
1073
+ }
1074
+
1075
+ ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];
1076
+
1077
+ if (configuration.conversionAccess == ConversionAccessibility.NONE) {
1078
+ revert ConversionConfigNotEnabled();
1079
+ }
1080
+
1081
+ uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);
1082
+ uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);
1083
+
1084
+ uint256 incentive = configuration.incentive;
1085
+ if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {
1086
+ incentive = 0;
1087
+ }
1088
+
1089
+ /// conversion rate after considering incentive(conversionWithIncentive)
1090
+ uint256 conversionWithIncentive = MANTISSA_ONE + incentive;
1091
+
1092
+ /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets
1093
+ /// multiplied by conversionWithIncentive which will be >= 1
1094
+ amountOutMantissa =
1095
+ (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /
1096
+ (tokenOutUnderlyingPrice * EXP_SCALE);
1097
+
1098
+ tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;
1099
+ }
1100
+
1101
+ /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut
1102
+ /// @dev This function retrieves values without altering token prices.
1103
+ /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive
1104
+ /// @param tokenAddressIn Address of the token to convert
1105
+ /// @param tokenAddressOut Address of the token to get after conversion
1106
+ /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion
1107
+ /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price
1108
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
1109
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
1110
+ function _getAmountIn(
1111
+ uint256 amountOutMantissa,
1112
+ address tokenAddressIn,
1113
+ address tokenAddressOut
1114
+ ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {
1115
+ if (amountOutMantissa == 0) {
1116
+ revert InsufficientOutputAmount();
1117
+ }
1118
+
1119
+ ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];
1120
+
1121
+ if (configuration.conversionAccess == ConversionAccessibility.NONE) {
1122
+ revert ConversionConfigNotEnabled();
1123
+ }
1124
+
1125
+ uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);
1126
+ uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);
1127
+
1128
+ uint256 incentive = configuration.incentive;
1129
+ if ((address(converterNetwork) != address(0)) && (converterNetwork.isTokenConverter(msg.sender))) {
1130
+ incentive = 0;
1131
+ }
1132
+
1133
+ /// conversion rate after considering incentive(conversionWithIncentive)
1134
+ uint256 conversionWithIncentive = MANTISSA_ONE + incentive;
1135
+ tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;
1136
+
1137
+ /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)
1138
+ amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up
1139
+ }
1140
+
1141
+ /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag
1142
+ /// @param tokenAddressIn Address of the token to convert
1143
+ /// @param tokenAddressOut Address of the token to get after conversion
1144
+ /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion
1145
+ function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {
1146
+ bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);
1147
+ if (
1148
+ (!(isConverter) &&
1149
+ (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==
1150
+ ConversionAccessibility.ONLY_FOR_CONVERTERS))
1151
+ ) {
1152
+ revert ConversionEnabledOnlyForPrivateConversions();
1153
+ }
1154
+ }
1155
+
1156
+ /// @dev To check, is conversion paused
1157
+ /// @custom:error ConversionTokensPaused is thrown when token conversion is paused
1158
+ function _checkConversionPaused() internal view {
1159
+ if (conversionPaused) {
1160
+ revert ConversionTokensPaused();
1161
+ }
1162
+ }
1163
+
1164
+ /// @dev Get base asset address of the destination contract
1165
+ /// @return Address of the base asset
1166
+ function _getDestinationBaseAsset() internal view virtual returns (address) {}
1167
+ }