@venusprotocol/protocol-reserve 1.1.0 → 1.2.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 (295) hide show
  1. package/README.md +17 -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/d38b6776f8d2919af17221fcc74eb552.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 +16 -16
  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 +582 -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 +14 -13
  129. package/contracts/ProtocolReserve/RiskFundStorage.sol +67 -0
  130. package/contracts/ProtocolReserve/RiskFundV2.sol +220 -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 +1168 -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 +102 -0
  144. package/contracts/Utils/ArrayHelpers.sol +41 -0
  145. package/contracts/Utils/Constants.sol +8 -0
  146. package/contracts/Utils/Validators.sol +26 -0
  147. package/deployments/bscmainnet.json +2039 -0
  148. package/deployments/bscmainnet_addresses.json +10 -0
  149. package/deployments/bsctestnet/BTCBPrimeConverter.json +218 -0
  150. package/deployments/bsctestnet/ConverterNetwork.json +723 -0
  151. package/deployments/bsctestnet/ConverterNetwork_Implementation.json +823 -0
  152. package/deployments/bsctestnet/ConverterNetwork_Proxy.json +277 -0
  153. package/deployments/bsctestnet/ETHPrimeConverter.json +218 -0
  154. package/deployments/bsctestnet/ProtocolShareReserve_Implementation.json +79 -73
  155. package/deployments/bsctestnet/RiskFundConverter.json +2035 -0
  156. package/deployments/bsctestnet/RiskFundConverter_Implementation.json +2563 -0
  157. package/deployments/bsctestnet/RiskFundConverter_Proxy.json +403 -0
  158. package/deployments/bsctestnet/RiskFundV2_Implementation.json +1049 -0
  159. package/deployments/bsctestnet/SingleTokenConverterBeacon.json +206 -0
  160. package/deployments/bsctestnet/SingleTokenConverterImp.json +2164 -0
  161. package/deployments/bsctestnet/USDCPrimeConverter.json +218 -0
  162. package/deployments/bsctestnet/USDTPrimeConverter.json +218 -0
  163. package/deployments/bsctestnet/XVSVaultConverter.json +218 -0
  164. package/deployments/bsctestnet/XVSVaultTreasury.json +579 -0
  165. package/deployments/bsctestnet/XVSVaultTreasury_Implementation.json +603 -0
  166. package/deployments/bsctestnet/XVSVaultTreasury_Proxy.json +281 -0
  167. package/deployments/bsctestnet/solcInputs/5d85b28b6a601f301b9d986a9cab69e1.json +168 -0
  168. package/deployments/bsctestnet/solcInputs/ddce8674a6dbb661f5732619dd799a66.json +228 -0
  169. package/deployments/bsctestnet/solcInputs/f4de763d185e08f2949b0be700500ede.json +144 -0
  170. package/deployments/bsctestnet.json +10088 -0
  171. package/deployments/bsctestnet_addresses.json +27 -0
  172. package/deployments/ethereum.json +5 -0
  173. package/deployments/ethereum_addresses.json +5 -0
  174. package/deployments/sepolia.json +5 -0
  175. package/deployments/sepolia_addresses.json +5 -0
  176. package/dist/deploy/001-psr.d.ts +2 -0
  177. package/dist/deploy/001-psr.d.ts.map +1 -0
  178. package/dist/deploy/001-psr.js +68 -0
  179. package/dist/deploy/001-psr.js.map +1 -0
  180. package/dist/deploy/002-risk-fund-converter.d.ts +4 -0
  181. package/dist/deploy/002-risk-fund-converter.d.ts.map +1 -0
  182. package/dist/deploy/002-risk-fund-converter.js +80 -0
  183. package/dist/deploy/002-risk-fund-converter.js.map +1 -0
  184. package/dist/deploy/003-xvs-vault-teasury.d.ts +2 -0
  185. package/dist/deploy/003-xvs-vault-teasury.d.ts.map +1 -0
  186. package/dist/deploy/003-xvs-vault-teasury.js +43 -0
  187. package/dist/deploy/003-xvs-vault-teasury.js.map +1 -0
  188. package/dist/deploy/004-single-token-converter.d.ts +4 -0
  189. package/dist/deploy/004-single-token-converter.d.ts.map +1 -0
  190. package/dist/deploy/004-single-token-converter.js +62 -0
  191. package/dist/deploy/004-single-token-converter.js.map +1 -0
  192. package/dist/deploy/005-converter-network.d.ts +2 -0
  193. package/dist/deploy/005-converter-network.d.ts.map +1 -0
  194. package/dist/deploy/005-converter-network.js +41 -0
  195. package/dist/deploy/005-converter-network.js.map +1 -0
  196. package/dist/hardhat.config.d.ts +15 -0
  197. package/dist/hardhat.config.d.ts.map +1 -0
  198. package/dist/hardhat.config.js +216 -0
  199. package/dist/hardhat.config.js.map +1 -0
  200. package/package.json +23 -21
  201. package/typechain/AbstractTokenConverter.d.ts +1775 -0
  202. package/typechain/AccessControl.d.ts +388 -0
  203. package/typechain/BeaconProxy.d.ts +126 -0
  204. package/typechain/BoundValidatorInterface.d.ts +126 -0
  205. package/typechain/ConverterNetwork.d.ts +723 -0
  206. package/typechain/{PoolRegistryInterface.d.ts → ERC165.d.ts} +20 -25
  207. package/typechain/ERC1967Upgrade.d.ts +126 -0
  208. package/typechain/IAbstractTokenConverter.d.ts +773 -0
  209. package/typechain/IBeacon.d.ts +101 -0
  210. package/typechain/IComptroller.d.ts +136 -0
  211. package/typechain/IConverterNetwork.d.ts +292 -0
  212. package/typechain/IERC165.d.ts +116 -0
  213. package/typechain/{ComptrollerInterface.d.ts → IERC1822Proxiable.d.ts} +11 -11
  214. package/typechain/IERC1967.d.ts +126 -0
  215. package/typechain/IPoolRegistry.d.ts +155 -0
  216. package/typechain/IRiskFund.d.ts +200 -0
  217. package/typechain/IRiskFundConverter.d.ts +138 -0
  218. package/typechain/IRiskFundGetters.d.ts +103 -0
  219. package/typechain/IShortfall.d.ts +110 -0
  220. package/typechain/IXVSVault.d.ts +95 -0
  221. package/typechain/MaxLoopsLimitHelpersStorage.d.ts +101 -0
  222. package/typechain/MockACM.d.ts +615 -0
  223. package/typechain/MockArraySorter.d.ts +118 -0
  224. package/typechain/MockConverter.d.ts +1969 -0
  225. package/typechain/MockDeflatingToken.d.ts +486 -0
  226. package/typechain/MockRiskFundConverter.d.ts +2479 -0
  227. package/typechain/MockToken.d.ts +36 -0
  228. package/typechain/OracleInterface.d.ts +98 -0
  229. package/typechain/Ownable.d.ts +181 -0
  230. package/typechain/PausableUpgradeable.d.ts +129 -0
  231. package/typechain/ProtocolShareReserve.d.ts +6 -6
  232. package/typechain/Proxy.d.ts +78 -0
  233. package/typechain/ReserveHelpersStorage.d.ts +300 -0
  234. package/typechain/ResilientOracle.d.ts +1034 -0
  235. package/typechain/ResilientOracleInterface.d.ts +192 -0
  236. package/typechain/RiskFundConverter.d.ts +2235 -0
  237. package/typechain/RiskFundV1Storage.d.ts +353 -0
  238. package/typechain/RiskFundV2.d.ts +893 -0
  239. package/typechain/RiskFundV2Storage.d.ts +372 -0
  240. package/typechain/SingleTokenConverter.d.ts +1944 -0
  241. package/typechain/TwapInterface.d.ts +124 -0
  242. package/typechain/UpgradeableBeacon.d.ts +240 -0
  243. package/typechain/VBep20Interface.d.ts +379 -0
  244. package/typechain/XVSVaultTreasury.d.ts +515 -0
  245. package/typechain/factories/AbstractTokenConverter__factory.ts +1297 -0
  246. package/typechain/factories/AccessControl__factory.ts +227 -0
  247. package/typechain/factories/BeaconProxy__factory.ts +133 -0
  248. package/typechain/factories/BoundValidatorInterface__factory.ts +59 -0
  249. package/typechain/factories/ConverterNetwork__factory.ts +502 -0
  250. package/typechain/factories/ERC165__factory.ts +39 -0
  251. package/typechain/factories/ERC1967Upgrade__factory.ts +71 -0
  252. package/typechain/factories/IAbstractTokenConverter__factory.ts +466 -0
  253. package/typechain/factories/IBeacon__factory.ts +36 -0
  254. package/typechain/factories/IComptroller__factory.ts +68 -0
  255. package/typechain/factories/IConverterNetwork__factory.ts +142 -0
  256. package/typechain/factories/{ComptrollerInterface__factory.ts → IERC165__factory.ts} +14 -15
  257. package/typechain/factories/IERC1822Proxiable__factory.ts +39 -0
  258. package/typechain/factories/IERC1967__factory.ts +68 -0
  259. package/typechain/factories/IPoolRegistry__factory.ts +66 -0
  260. package/typechain/factories/{PoolRegistryInterface__factory.ts → IRiskFundConverter__factory.ts} +28 -19
  261. package/typechain/factories/IRiskFundGetters__factory.ts +39 -0
  262. package/typechain/factories/IRiskFund__factory.ts +89 -0
  263. package/typechain/factories/IShortfall__factory.ts +36 -0
  264. package/typechain/factories/IXVSVault__factory.ts +36 -0
  265. package/typechain/factories/MaxLoopsLimitHelpersStorage__factory.ts +75 -0
  266. package/typechain/factories/MockACM__factory.ts +411 -0
  267. package/typechain/factories/MockArraySorter__factory.ts +85 -0
  268. package/typechain/factories/MockConverter__factory.ts +1439 -0
  269. package/typechain/factories/MockDeflatingToken__factory.ts +389 -0
  270. package/typechain/factories/MockRiskFundConverter__factory.ts +1828 -0
  271. package/typechain/factories/MockToken__factory.ts +19 -1
  272. package/typechain/factories/OracleInterface__factory.ts +45 -0
  273. package/typechain/factories/Ownable__factory.ts +75 -0
  274. package/typechain/factories/PausableUpgradeable__factory.ts +78 -0
  275. package/typechain/factories/ProtocolShareReserve__factory.ts +15 -15
  276. package/typechain/factories/Proxy__factory.ts +28 -0
  277. package/typechain/factories/ReserveHelpersStorage__factory.ts +188 -0
  278. package/typechain/factories/ResilientOracleInterface__factory.ts +94 -0
  279. package/typechain/factories/ResilientOracle__factory.ts +710 -0
  280. package/typechain/factories/RiskFundConverter__factory.ts +1694 -0
  281. package/typechain/factories/RiskFundV1Storage__factory.ts +223 -0
  282. package/typechain/factories/RiskFundV2Storage__factory.ts +236 -0
  283. package/typechain/factories/RiskFundV2__factory.ts +624 -0
  284. package/typechain/factories/SingleTokenConverter__factory.ts +1441 -0
  285. package/typechain/factories/TwapInterface__factory.ts +61 -0
  286. package/typechain/factories/UpgradeableBeacon__factory.ts +163 -0
  287. package/typechain/factories/VBep20Interface__factory.ts +261 -0
  288. package/typechain/factories/XVSVaultTreasury__factory.ts +365 -0
  289. package/typechain/index.ts +84 -4
  290. package/artifacts/build-info/0bf08ffb3b10e68a2b3f4538fccc61c5.json +0 -1
  291. package/artifacts/contracts/Interfaces/ComptrollerInterface.sol/ComptrollerInterface.dbg.json +0 -4
  292. package/artifacts/contracts/Interfaces/PoolRegistryInterface.sol/PoolRegistryInterface.dbg.json +0 -4
  293. package/contracts/Interfaces/ComptrollerInterface.sol +0 -6
  294. package/contracts/Interfaces/PoolRegistryInterface.sol +0 -7
  295. package/deploy/1-deploy.ts +0 -64
@@ -0,0 +1,1168 @@
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 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
+ amountConvertedMantissa = amountOutMantissa;
608
+ uint256 tokenInToOutConversion;
609
+ (amountInMantissa, tokenInToOutConversion) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);
610
+ uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);
611
+
612
+ /// If contract has less liquidity for tokenAddressOut than amountOutMantissa
613
+ if (maxTokenOutReserve < amountOutMantissa) {
614
+ amountInMantissa = ((maxTokenOutReserve * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up
615
+ amountConvertedMantissa = maxTokenOutReserve;
616
+ }
617
+ }
618
+
619
+ /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn
620
+ /// @param amountInMantissa Amount of tokenAddressIn
621
+ /// @param tokenAddressIn Address of the token to convert
622
+ /// @param tokenAddressOut Address of the token to get after conversion
623
+ /// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion
624
+ /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion
625
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
626
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
627
+ function getUpdatedAmountOut(
628
+ uint256 amountInMantissa,
629
+ address tokenAddressIn,
630
+ address tokenAddressOut
631
+ ) public returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa) {
632
+ priceOracle.updateAssetPrice(tokenAddressIn);
633
+ priceOracle.updateAssetPrice(tokenAddressOut);
634
+
635
+ (amountOutMantissa, ) = _getAmountOut(amountInMantissa, tokenAddressIn, tokenAddressOut);
636
+ amountConvertedMantissa = amountInMantissa;
637
+ }
638
+
639
+ /// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut
640
+ /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive
641
+ /// @param tokenAddressIn Address of the token to convert
642
+ /// @param tokenAddressOut Address of the token to get after conversion
643
+ /// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion
644
+ /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion
645
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
646
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
647
+ function getUpdatedAmountIn(
648
+ uint256 amountOutMantissa,
649
+ address tokenAddressIn,
650
+ address tokenAddressOut
651
+ ) public returns (uint256 amountConvertedMantissa, uint256 amountInMantissa) {
652
+ priceOracle.updateAssetPrice(tokenAddressIn);
653
+ priceOracle.updateAssetPrice(tokenAddressOut);
654
+
655
+ (amountInMantissa, ) = _getAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);
656
+ amountConvertedMantissa = amountOutMantissa;
657
+ }
658
+
659
+ /// @notice This method updated the states of this contract after getting funds from PSR
660
+ /// after settling the amount(if any) through privateConversion between converters
661
+ /// @dev This function is called by protocolShareReserve
662
+ /// @dev call _updateAssetsState to update the states related to the comptroller and asset transfer to the specific converter then
663
+ /// it calls the _privateConversion which will convert the asset into destination's base asset and transfer it to destination address
664
+ /// @param comptroller Comptroller address (pool)
665
+ /// @param asset Asset address
666
+ function updateAssetsState(address comptroller, address asset) public nonReentrant {
667
+ uint256 balanceDiff = _updateAssetsState(comptroller, asset);
668
+ if (balanceDiff > 0) {
669
+ _privateConversion(comptroller, asset, balanceDiff);
670
+ }
671
+ }
672
+
673
+ /// @notice Set the configuration for new or existing conversion pair
674
+ /// @param tokenAddressIn Address of tokenIn
675
+ /// @param tokenAddressOut Address of tokenOut
676
+ /// @param conversionConfig ConversionConfig config details to update
677
+ /// @custom:event Emits ConversionConfigUpdated event on success
678
+ /// @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager
679
+ /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero
680
+ /// @custom:error NonZeroIncentiveForPrivateConversion is thrown when incentive is non zero for private conversion
681
+ /// @custom:access Controlled by AccessControlManager
682
+ function setConversionConfig(
683
+ address tokenAddressIn,
684
+ address tokenAddressOut,
685
+ ConversionConfig calldata conversionConfig
686
+ ) public {
687
+ _checkAccessAllowed("setConversionConfig(address,address,ConversionConfig)");
688
+ ensureNonzeroAddress(tokenAddressIn);
689
+ ensureNonzeroAddress(tokenAddressOut);
690
+
691
+ if (conversionConfig.incentive > MAX_INCENTIVE) {
692
+ revert IncentiveTooHigh(conversionConfig.incentive, MAX_INCENTIVE);
693
+ }
694
+
695
+ if (
696
+ (tokenAddressIn == tokenAddressOut) ||
697
+ (tokenAddressIn != _getDestinationBaseAsset()) ||
698
+ conversionConfigurations[tokenAddressOut][tokenAddressIn].conversionAccess != ConversionAccessibility.NONE
699
+ ) {
700
+ revert InvalidTokenConfigAddresses();
701
+ }
702
+
703
+ if (
704
+ (conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) &&
705
+ conversionConfig.incentive != 0
706
+ ) {
707
+ revert NonZeroIncentiveForPrivateConversion();
708
+ }
709
+
710
+ if (
711
+ ((conversionConfig.conversionAccess == ConversionAccessibility.ONLY_FOR_CONVERTERS) ||
712
+ (conversionConfig.conversionAccess == ConversionAccessibility.ALL)) &&
713
+ (address(converterNetwork) == address(0))
714
+ ) {
715
+ revert InvalidConverterNetwork();
716
+ }
717
+
718
+ ConversionConfig storage configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];
719
+
720
+ emit ConversionConfigUpdated(
721
+ tokenAddressIn,
722
+ tokenAddressOut,
723
+ configuration.incentive,
724
+ conversionConfig.incentive,
725
+ configuration.conversionAccess,
726
+ conversionConfig.conversionAccess
727
+ );
728
+
729
+ if (conversionConfig.conversionAccess == ConversionAccessibility.NONE) {
730
+ delete conversionConfigurations[tokenAddressIn][tokenAddressOut];
731
+ } else {
732
+ configuration.incentive = conversionConfig.incentive;
733
+ configuration.conversionAccess = conversionConfig.conversionAccess;
734
+ }
735
+ }
736
+
737
+ /// @notice Get the balance for specific token
738
+ /// @param token Address of the token
739
+ /// @return tokenBalance Balance of the token the contract has
740
+ function balanceOf(address token) public view virtual returns (uint256 tokenBalance);
741
+
742
+ /// @dev Operations to perform before sweeping tokens
743
+ /// @param token Address of the token
744
+ /// @param amount Amount transferred to address(to)
745
+ function preSweepToken(address token, uint256 amount) internal virtual {}
746
+
747
+ /// @dev Converts exact amount of tokenAddressIn for tokenAddressOut
748
+ /// @param amountInMantissa Amount of tokenAddressIn
749
+ /// @param amountOutMinMantissa Min amount of tokenAddressOut required as output
750
+ /// @param tokenAddressIn Address of the token to convert
751
+ /// @param tokenAddressOut Address of the token to get after conversion
752
+ /// @param to Address of the tokenAddressOut receiver
753
+ /// @return actualAmountIn Actual amount of tokenAddressIn transferred
754
+ /// @return amountOutMantissa Actual amount of tokenAddressOut transferred
755
+ /// @custom:error AmountOutLowerThanMinRequired error is thrown when amount of output tokenAddressOut is less than amountOutMinMantissa
756
+ function _convertExactTokens(
757
+ uint256 amountInMantissa,
758
+ uint256 amountOutMinMantissa,
759
+ address tokenAddressIn,
760
+ address tokenAddressOut,
761
+ address to
762
+ ) internal returns (uint256 actualAmountIn, uint256 amountOutMantissa) {
763
+ _checkPrivateConversion(tokenAddressIn, tokenAddressOut);
764
+ actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);
765
+
766
+ (, amountOutMantissa) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);
767
+
768
+ if (amountOutMantissa < amountOutMinMantissa) {
769
+ revert AmountOutLowerThanMinRequired(amountOutMantissa, amountOutMinMantissa);
770
+ }
771
+
772
+ _doTransferOut(tokenAddressOut, to, amountOutMantissa);
773
+ }
774
+
775
+ /// @dev Converts tokens for tokenAddressIn for exact amount of tokenAddressOut used for non deflationry tokens
776
+ /// it is called by convertForExactTokens function
777
+ /// @param amountInMaxMantissa Max amount of tokenAddressIn
778
+ /// @param amountOutMantissa Amount of tokenAddressOut required as output
779
+ /// @param tokenAddressIn Address of the token to convert
780
+ /// @param tokenAddressOut Address of the token to get after conversion
781
+ /// @param to Address of the tokenAddressOut receiver
782
+ /// @return actualAmountIn Actual amount of tokenAddressIn transferred
783
+ /// @return actualAmountOut Actual amount of tokenAddressOut transferred
784
+ /// @custom:error DeflationaryTokenNotSupported is thrown if tokenAddressIn is deflationary token
785
+ /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa
786
+ function _convertForExactTokens(
787
+ uint256 amountInMaxMantissa,
788
+ uint256 amountOutMantissa,
789
+ address tokenAddressIn,
790
+ address tokenAddressOut,
791
+ address to
792
+ ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {
793
+ _checkPrivateConversion(tokenAddressIn, tokenAddressOut);
794
+ (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);
795
+
796
+ actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);
797
+
798
+ if (actualAmountIn != amountInMantissa) {
799
+ revert DeflationaryTokenNotSupported();
800
+ }
801
+
802
+ if (actualAmountIn > amountInMaxMantissa) {
803
+ revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);
804
+ }
805
+
806
+ _doTransferOut(tokenAddressOut, to, amountOutMantissa);
807
+ actualAmountOut = amountOutMantissa;
808
+ }
809
+
810
+ /// @dev Converts tokens for tokenAddressIn for the amount of tokenAddressOut used for deflationary tokens
811
+ /// it is called by convertForExactTokensSupportingFeeOnTransferTokens function
812
+ /// @param amountInMaxMantissa Max amount of tokenAddressIn
813
+ /// @param amountOutMantissa Amount of tokenAddressOut required as output
814
+ /// @param tokenAddressIn Address of the token to convert
815
+ /// @param tokenAddressOut Address of the token to get after conversion
816
+ /// @param to Address of the tokenAddressOut receiver
817
+ /// @return actualAmountIn Actual amount of tokenAddressIn transferred
818
+ /// @return actualAmountOut Actual amount of tokenAddressOut transferred
819
+ /// @custom:error AmountInHigherThanMax error is thrown when amount of tokenAddressIn is higher than amountInMaxMantissa
820
+ function _convertForExactTokensSupportingFeeOnTransferTokens(
821
+ uint256 amountInMaxMantissa,
822
+ uint256 amountOutMantissa,
823
+ address tokenAddressIn,
824
+ address tokenAddressOut,
825
+ address to
826
+ ) internal returns (uint256 actualAmountIn, uint256 actualAmountOut) {
827
+ _checkPrivateConversion(tokenAddressIn, tokenAddressOut);
828
+ (, uint256 amountInMantissa) = getUpdatedAmountIn(amountOutMantissa, tokenAddressIn, tokenAddressOut);
829
+
830
+ if (amountInMantissa > amountInMaxMantissa) {
831
+ revert AmountInHigherThanMax(amountInMantissa, amountInMaxMantissa);
832
+ }
833
+
834
+ actualAmountIn = _doTransferIn(tokenAddressIn, amountInMantissa);
835
+
836
+ (, actualAmountOut) = getUpdatedAmountOut(actualAmountIn, tokenAddressIn, tokenAddressOut);
837
+
838
+ _doTransferOut(tokenAddressOut, to, actualAmountOut);
839
+ }
840
+
841
+ /// @dev return actualAmountOut from reserves for tokenAddressOut
842
+ /// @param tokenAddressOut Address of the token to get after conversion
843
+ /// @param to Address of the tokenAddressOut receiver
844
+ /// @param amountConvertedMantissa Amount of tokenAddressOut supposed to get transferred
845
+ /// @custom:error InsufficientPoolLiquidity If contract has less liquidity for tokenAddressOut than amountOutMantissa
846
+ function _doTransferOut(
847
+ address tokenAddressOut,
848
+ address to,
849
+ uint256 amountConvertedMantissa
850
+ ) internal {
851
+ uint256 maxTokenOutReserve = balanceOf(tokenAddressOut);
852
+
853
+ /// If contract has less liquidity for tokenAddressOut than amountOutMantissa
854
+ if (maxTokenOutReserve < amountConvertedMantissa) {
855
+ revert InsufficientPoolLiquidity();
856
+ }
857
+
858
+ _preTransferHook(tokenAddressOut, amountConvertedMantissa);
859
+
860
+ IERC20Upgradeable tokenOut = IERC20Upgradeable(tokenAddressOut);
861
+ tokenOut.safeTransfer(to, amountConvertedMantissa);
862
+ }
863
+
864
+ /// @notice Transfer tokenAddressIn from user to destination
865
+ /// @param tokenAddressIn Address of the token to convert
866
+ /// @param amountInMantissa Amount of tokenAddressIn
867
+ /// @return actualAmountIn Actual amount transferred to destination
868
+ function _doTransferIn(address tokenAddressIn, uint256 amountInMantissa) internal returns (uint256 actualAmountIn) {
869
+ IERC20Upgradeable tokenIn = IERC20Upgradeable(tokenAddressIn);
870
+ uint256 balanceBeforeDestination = tokenIn.balanceOf(destinationAddress);
871
+ tokenIn.safeTransferFrom(msg.sender, destinationAddress, amountInMantissa);
872
+ uint256 balanceAfterDestination = tokenIn.balanceOf(destinationAddress);
873
+ actualAmountIn = balanceAfterDestination - balanceBeforeDestination;
874
+ }
875
+
876
+ /// @dev Sets a new price oracle
877
+ /// @param priceOracle_ Address of the new price oracle to set
878
+ /// @custom:event Emits PriceOracleUpdated event on success
879
+ /// @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero
880
+ function _setPriceOracle(ResilientOracle priceOracle_) internal {
881
+ ensureNonzeroAddress(address(priceOracle_));
882
+ emit PriceOracleUpdated(priceOracle, priceOracle_);
883
+ priceOracle = priceOracle_;
884
+ }
885
+
886
+ /// @dev Sets a new destination address
887
+ /// @param destinationAddress_ The new destination address to be set
888
+ /// @custom:event Emits DestinationAddressUpdated event on success
889
+ /// @custom:error ZeroAddressNotAllowed is thrown when destination address is zero
890
+ function _setDestination(address destinationAddress_) internal {
891
+ ensureNonzeroAddress(destinationAddress_);
892
+ emit DestinationAddressUpdated(destinationAddress, destinationAddress_);
893
+ destinationAddress = destinationAddress_;
894
+ }
895
+
896
+ /// @notice Sets a converter network contract address
897
+ /// @param converterNetwork_ The converterNetwork address to be set
898
+ /// @custom:event Emits ConverterNetworkAddressUpdated event on success
899
+ /// @custom:error ZeroAddressNotAllowed is thrown when address is zero
900
+ function _setConverterNetwork(IConverterNetwork converterNetwork_) internal {
901
+ ensureNonzeroAddress(address(converterNetwork_));
902
+ emit ConverterNetworkAddressUpdated(address(converterNetwork), address(converterNetwork_));
903
+ converterNetwork = converterNetwork_;
904
+ }
905
+
906
+ /// @notice Min amount to convert setter
907
+ /// @param minAmountToConvert_ Min amount to convert
908
+ /// @custom:event MinAmountToConvertUpdated is emitted in success
909
+ /// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0
910
+ function _setMinAmountToConvert(uint256 minAmountToConvert_) internal {
911
+ ensureNonzeroValue(minAmountToConvert_);
912
+ emit MinAmountToConvertUpdated(minAmountToConvert, minAmountToConvert_);
913
+ minAmountToConvert = minAmountToConvert_;
914
+ }
915
+
916
+ /// @dev Hook to perform after converting tokens
917
+ /// @param tokenAddressIn Address of the token to convert
918
+ /// @param tokenAddressOut Address of the token to get after conversion
919
+ /// @param amountIn Amount of tokenIn converted
920
+ /// @param amountOut Amount of tokenOut converted
921
+ function _postConversionHook(
922
+ address tokenAddressIn,
923
+ address tokenAddressOut,
924
+ uint256 amountIn,
925
+ uint256 amountOut
926
+ ) internal virtual {}
927
+
928
+ /// @param accessControlManager_ Access control manager contract address
929
+ /// @param priceOracle_ Resilient oracle address
930
+ /// @param destinationAddress_ Address at all incoming tokens will transferred to
931
+ /// @param minAmountToConvert_ minimum amount to convert
932
+ function __AbstractTokenConverter_init(
933
+ address accessControlManager_,
934
+ ResilientOracle priceOracle_,
935
+ address destinationAddress_,
936
+ uint256 minAmountToConvert_
937
+ ) internal onlyInitializing {
938
+ __AccessControlled_init(accessControlManager_);
939
+ __ReentrancyGuard_init();
940
+ __AbstractTokenConverter_init_unchained(priceOracle_, destinationAddress_, minAmountToConvert_);
941
+ }
942
+
943
+ /// @param priceOracle_ Resilient oracle address
944
+ /// @param destinationAddress_ Address at all incoming tokens will transferred to
945
+ /// @param minAmountToConvert_ minimum amount to convert
946
+ function __AbstractTokenConverter_init_unchained(
947
+ ResilientOracle priceOracle_,
948
+ address destinationAddress_,
949
+ uint256 minAmountToConvert_
950
+ ) internal onlyInitializing {
951
+ _setPriceOracle(priceOracle_);
952
+ _setDestination(destinationAddress_);
953
+ _setMinAmountToConvert(minAmountToConvert_);
954
+ conversionPaused = false;
955
+ }
956
+
957
+ /// @dev _updateAssetsState hook to update the states of reserves transferred for the specific comptroller
958
+ /// @param comptroller Comptroller address (pool)
959
+ /// @param asset Asset address
960
+ /// @return Amount of asset, for _privateConversion
961
+ function _updateAssetsState(address comptroller, address asset) internal virtual returns (uint256) {}
962
+
963
+ /// @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
964
+ /// destination contract as destination's base asset
965
+ /// @param comptroller Comptroller address (pool)
966
+ /// @param tokenAddressOut Address of the token transferred to converter, and through _privateConversion it will be converted into base asset
967
+ /// @param amountToConvert Amount of the tokenAddressOut transferred to converter
968
+ function _privateConversion(
969
+ address comptroller,
970
+ address tokenAddressOut,
971
+ uint256 amountToConvert
972
+ ) internal {
973
+ address tokenAddressIn = _getDestinationBaseAsset();
974
+ address _destinationAddress = destinationAddress;
975
+ uint256 convertedTokenInBalance;
976
+ if (address(converterNetwork) != address(0)) {
977
+ (address[] memory converterAddresses, uint256[] memory converterBalances) = converterNetwork
978
+ .findTokenConvertersForConverters(tokenAddressOut, tokenAddressIn);
979
+ uint256 convertersLength = converterAddresses.length;
980
+ for (uint256 i; i < convertersLength; ) {
981
+ if (converterBalances[i] == 0) break;
982
+ (, uint256 amountIn) = IAbstractTokenConverter(converterAddresses[i]).getUpdatedAmountIn(
983
+ converterBalances[i],
984
+ tokenAddressOut,
985
+ tokenAddressIn
986
+ );
987
+ if (amountIn > amountToConvert) {
988
+ amountIn = amountToConvert;
989
+ }
990
+
991
+ if (!_validateMinAmountToConvert(amountIn, tokenAddressOut)) {
992
+ break;
993
+ }
994
+
995
+ uint256 balanceBefore = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);
996
+
997
+ IERC20Upgradeable(tokenAddressOut).approve(converterAddresses[i], amountIn);
998
+ IAbstractTokenConverter(converterAddresses[i]).convertExactTokens(
999
+ amountIn,
1000
+ 0,
1001
+ tokenAddressOut,
1002
+ tokenAddressIn,
1003
+ _destinationAddress
1004
+ );
1005
+
1006
+ uint256 balanceAfter = IERC20Upgradeable(tokenAddressIn).balanceOf(_destinationAddress);
1007
+ amountToConvert -= amountIn;
1008
+ convertedTokenInBalance += (balanceAfter - balanceBefore);
1009
+
1010
+ if (amountToConvert == 0) break;
1011
+ unchecked {
1012
+ ++i;
1013
+ }
1014
+ }
1015
+ }
1016
+
1017
+ _postPrivateConversionHook(
1018
+ comptroller,
1019
+ tokenAddressIn,
1020
+ convertedTokenInBalance,
1021
+ tokenAddressOut,
1022
+ amountToConvert
1023
+ );
1024
+ }
1025
+
1026
+ /// @dev This hook is used to update states for the converter after the privateConversion
1027
+ /// @param comptroller Comptroller address (pool)
1028
+ /// @param tokenAddressIn Address of the destination's base asset
1029
+ /// @param convertedTokenInBalance Amount of the base asset received after the conversion
1030
+ /// @param tokenAddressOut Address of the asset transferred to other converter in exchange of base asset
1031
+ /// @param convertedTokenOutBalance Amount of tokenAddressOut transferred from this converter
1032
+ function _postPrivateConversionHook(
1033
+ address comptroller,
1034
+ address tokenAddressIn,
1035
+ uint256 convertedTokenInBalance,
1036
+ address tokenAddressOut,
1037
+ uint256 convertedTokenOutBalance
1038
+ ) internal virtual {}
1039
+
1040
+ /// @notice This hook is used to update the state for asset reserves before transferring tokenOut to user
1041
+ /// @param tokenOutAddress Address of the asset to be transferred to the user
1042
+ /// @param amountOut Amount of tokenAddressOut transferred from this converter
1043
+ function _preTransferHook(address tokenOutAddress, uint256 amountOut) internal virtual {}
1044
+
1045
+ /// @dev Checks if amount to convert is greater than minimum amount to convert or not
1046
+ /// @param amountIn The amount to convert
1047
+ /// @param tokenAddress Address of the token
1048
+ /// @return isValid true if amount to convert is greater than minimum amount to convert
1049
+ function _validateMinAmountToConvert(uint256 amountIn, address tokenAddress) internal returns (bool isValid) {
1050
+ priceOracle.updateAssetPrice(tokenAddress);
1051
+ uint256 amountInInUsd = (priceOracle.getPrice(tokenAddress) * amountIn) / EXP_SCALE;
1052
+
1053
+ if (amountInInUsd >= minAmountToConvert) {
1054
+ isValid = true;
1055
+ }
1056
+ }
1057
+
1058
+ /// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn
1059
+ /// @dev This function retrieves values without altering token prices.
1060
+ /// @param amountInMantissa Amount of tokenAddressIn
1061
+ /// @param tokenAddressIn Address of the token to convert
1062
+ /// @param tokenAddressOut Address of the token to get after conversion
1063
+ /// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion
1064
+ /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price
1065
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
1066
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
1067
+ function _getAmountOut(
1068
+ uint256 amountInMantissa,
1069
+ address tokenAddressIn,
1070
+ address tokenAddressOut
1071
+ ) internal view returns (uint256 amountOutMantissa, uint256 tokenInToOutConversion) {
1072
+ if (amountInMantissa == 0) {
1073
+ revert InsufficientInputAmount();
1074
+ }
1075
+
1076
+ ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];
1077
+
1078
+ if (configuration.conversionAccess == ConversionAccessibility.NONE) {
1079
+ revert ConversionConfigNotEnabled();
1080
+ }
1081
+
1082
+ uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);
1083
+ uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);
1084
+
1085
+ uint256 incentive = configuration.incentive;
1086
+ if (address(converterNetwork) != address(0) && (converterNetwork.isTokenConverter(msg.sender))) {
1087
+ incentive = 0;
1088
+ }
1089
+
1090
+ /// conversion rate after considering incentive(conversionWithIncentive)
1091
+ uint256 conversionWithIncentive = MANTISSA_ONE + incentive;
1092
+
1093
+ /// amount of tokenAddressOut after including incentive as amountOutMantissa will be greater than actual as it gets
1094
+ /// multiplied by conversionWithIncentive which will be >= 1
1095
+ amountOutMantissa =
1096
+ (amountInMantissa * tokenInUnderlyingPrice * conversionWithIncentive) /
1097
+ (tokenOutUnderlyingPrice * EXP_SCALE);
1098
+
1099
+ tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;
1100
+ }
1101
+
1102
+ /// @dev To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut
1103
+ /// @dev This function retrieves values without altering token prices.
1104
+ /// @param amountOutMantissa Amount of tokenAddressOut user wants to receive
1105
+ /// @param tokenAddressIn Address of the token to convert
1106
+ /// @param tokenAddressOut Address of the token to get after conversion
1107
+ /// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion
1108
+ /// @return tokenInToOutConversion Ratio of tokenIn price and incentive for conversion with tokenOut price
1109
+ /// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
1110
+ /// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
1111
+ function _getAmountIn(
1112
+ uint256 amountOutMantissa,
1113
+ address tokenAddressIn,
1114
+ address tokenAddressOut
1115
+ ) internal view returns (uint256 amountInMantissa, uint256 tokenInToOutConversion) {
1116
+ if (amountOutMantissa == 0) {
1117
+ revert InsufficientOutputAmount();
1118
+ }
1119
+
1120
+ ConversionConfig memory configuration = conversionConfigurations[tokenAddressIn][tokenAddressOut];
1121
+
1122
+ if (configuration.conversionAccess == ConversionAccessibility.NONE) {
1123
+ revert ConversionConfigNotEnabled();
1124
+ }
1125
+
1126
+ uint256 tokenInUnderlyingPrice = priceOracle.getPrice(tokenAddressIn);
1127
+ uint256 tokenOutUnderlyingPrice = priceOracle.getPrice(tokenAddressOut);
1128
+
1129
+ uint256 incentive = configuration.incentive;
1130
+ if ((address(converterNetwork) != address(0)) && (converterNetwork.isTokenConverter(msg.sender))) {
1131
+ incentive = 0;
1132
+ }
1133
+
1134
+ /// conversion rate after considering incentive(conversionWithIncentive)
1135
+ uint256 conversionWithIncentive = MANTISSA_ONE + incentive;
1136
+ tokenInToOutConversion = (tokenInUnderlyingPrice * conversionWithIncentive) / tokenOutUnderlyingPrice;
1137
+
1138
+ /// amount of tokenAddressIn after considering incentive(i.e. amountInMantissa will be less than actual amountInMantissa if incentive > 0)
1139
+ amountInMantissa = ((amountOutMantissa * EXP_SCALE) + tokenInToOutConversion - 1) / tokenInToOutConversion; //round-up
1140
+ }
1141
+
1142
+ /// @dev Check if msg.sender is allowed to convert as per onlyForPrivateConversions flag
1143
+ /// @param tokenAddressIn Address of the token to convert
1144
+ /// @param tokenAddressOut Address of the token to get after conversion
1145
+ /// @custom:error ConversionEnabledOnlyForPrivateConversions is thrown when conversion is only enabled for private conversion
1146
+ function _checkPrivateConversion(address tokenAddressIn, address tokenAddressOut) internal view {
1147
+ bool isConverter = (address(converterNetwork) != address(0)) && converterNetwork.isTokenConverter(msg.sender);
1148
+ if (
1149
+ (!(isConverter) &&
1150
+ (conversionConfigurations[tokenAddressIn][tokenAddressOut].conversionAccess ==
1151
+ ConversionAccessibility.ONLY_FOR_CONVERTERS))
1152
+ ) {
1153
+ revert ConversionEnabledOnlyForPrivateConversions();
1154
+ }
1155
+ }
1156
+
1157
+ /// @dev To check, is conversion paused
1158
+ /// @custom:error ConversionTokensPaused is thrown when token conversion is paused
1159
+ function _checkConversionPaused() internal view {
1160
+ if (conversionPaused) {
1161
+ revert ConversionTokensPaused();
1162
+ }
1163
+ }
1164
+
1165
+ /// @dev Get base asset address of the destination contract
1166
+ /// @return Address of the base asset
1167
+ function _getDestinationBaseAsset() internal view virtual returns (address) {}
1168
+ }