├── discord-export ├── Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files │ ├── C4-banner-7C19B.png │ ├── 3-FB033.png │ ├── 5-E9BDB.png │ ├── IMG_9458-C2A76.png │ ├── unknown-9507B.png │ ├── 786914635986501654-46CF8.png │ ├── 851893826846457866-1AD3D.png │ ├── 851893827315826708-F59C0.png │ ├── 851893827706028033-9A97C.png │ ├── ggsans-italic-400-E988B.woff2 │ ├── ggsans-italic-500-0777F.woff2 │ ├── ggsans-italic-600-CB411.woff2 │ ├── ggsans-italic-700-891AC.woff2 │ ├── ggsans-italic-800-D36B0.woff2 │ ├── ggsans-normal-400-1456D.woff2 │ ├── ggsans-normal-500-89CE5.woff2 │ ├── ggsans-normal-600-C1EA8.woff2 │ ├── ggsans-normal-700-1949A.woff2 │ ├── ggsans-normal-800-58487.woff2 │ ├── 2a9faff195fe333526cfe6ae6fce1420-927E9.png │ ├── 467517ffa947930b8383c77934903657-6CBF8.png │ ├── 58b16f0c-7fca-4180-bec0-a9a1e71e7aa3-04B6A │ ├── 5960c5502dd09d4875482231f43edbc5-F05FC.png │ ├── 5d12e3b47f1005d10059611eeaf3a79d-E9754.png │ ├── 5f978694dec96afc1640b5426003aef1-3E74E.png │ ├── 60973beb51aebcfc8ef49e01c59da7c1-C5171.png │ ├── 67594ee4b4d1fc03bca468327a0d145b-0C614.png │ ├── 9503f567dabd2781b3d25827ceb83075-313E1.png │ ├── ae70f07a06c1c7e983291bb14a1bed7f-F1116.png │ ├── c9cb30134c634c9e02d0c64df4922803-1AAF2.png │ ├── e30d0fe5b5a56ace70463fe4fb765489-6D670.png │ ├── 1f50d-195C0.svg │ ├── 1f972-F415D.svg │ ├── solarized-dark.min-BA98F.css │ ├── 1f525-8FE4F.svg │ ├── 1f4dc-AC641.svg │ ├── 1f604-BF863.svg │ ├── 1f606-BE94E.svg │ ├── 1f6a8-A8AB3.svg │ ├── 1f3c6-621A1.svg │ ├── 1f9d1-5BC80.svg │ ├── 2696-15F4A.svg │ ├── 1f64f-22B8D.svg │ ├── 1f44b-8A059.svg │ ├── 1f923-5854E.svg │ ├── 1f44d-27259.svg │ ├── 1f602-168C5.svg │ ├── 1f4c6-44E30.svg │ ├── 1f911-F346C.svg │ └── 1f43a-EB486.svg └── Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].txt_Files │ ├── C4-banner-7C19B.png │ ├── IMG_9458-C2A76.png │ ├── unknown-9507B.png │ └── 58b16f0c-7fca-4180-bec0-a9a1e71e7aa3-04B6A ├── img ├── AlchemixV2_elixir.jpg ├── AlchemixV2_token_flows.jpg ├── AlchemixV2_function_calls.jpg └── AlchemixV2_proxy_configurations.jpg ├── contracts-full ├── interfaces │ ├── ITransmuterV1.sol │ ├── convex │ │ ├── IConvexBooster.sol │ │ ├── IConvexToken.sol │ │ └── IConvexRewards.sol │ ├── vesper │ │ ├── IVesperRewards.sol │ │ └── IVesperPool.sol │ ├── IALCXSource.sol │ ├── lido │ │ ├── IStETH.sol │ │ └── IWstETH.sol │ ├── compound │ │ ├── IInterestRateModel.sol │ │ └── ICERC20.sol │ ├── IERC20TokenReceiver.sol │ ├── alchemist │ │ └── IAlchemistV2Immutables.sol │ ├── IERC20Mintable.sol │ ├── IAaveFlashLoanReceiver.sol │ ├── external │ │ ├── IProxyAdmin.sol │ │ ├── aave │ │ │ ├── IWethGateway.sol │ │ │ ├── ILendingPoolAddressesProviderRegistry.sol │ │ │ ├── IScaledBalanceToken.sol │ │ │ ├── DataTypes.sol │ │ │ └── ILendingPoolAddressesProvider.sol │ │ ├── IWETH9.sol │ │ └── tether │ │ │ └── ITetherToken.sol │ ├── IAlchemistV2.sol │ ├── ICurveFactoryethpool.sol │ ├── IERC20Metadata.sol │ ├── IWETH9.sol │ ├── IERC20Burnable.sol │ ├── rocket │ │ ├── IRETH.sol │ │ └── IRocketStorage.sol │ ├── IAlchemicToken.sol │ ├── IERC3156FlashBorrower.sol │ ├── IMulticall.sol │ ├── IERC20PermitAllowed.sol │ ├── ICurveMetapool.sol │ ├── curve │ │ ├── IStableSwap2Pool.sol │ │ ├── IStableSwap3Pool.sol │ │ ├── IStableMetaPool.sol │ │ └── IEthStableMetaPool.sol │ ├── IERC3156FlashLender.sol │ ├── ITokenAdapter.sol │ ├── IStakingPools.sol │ ├── test │ │ └── ITestYieldToken.sol │ ├── IWhitelist.sol │ └── IWETHGateway.sol ├── test │ ├── TestErc20Receiver.sol │ ├── TestWhitelistedCaller.sol │ ├── TestTransmuter.sol │ ├── TestAlchemicToken.sol │ ├── TestSets.sol │ ├── ERC20Mock.sol │ ├── TestFlashBorrower.sol │ ├── TestWhitelisted.sol │ ├── TransmuterBufferMock.sol │ ├── TestYieldTokenAdapter.sol │ └── TransmuterMock.sol ├── CrossChainCanonicalGALCX.sol ├── base │ ├── Errors.sol │ ├── Multicall.sol │ ├── Mutex.sol │ └── SelfPermit.sol ├── libraries │ ├── RocketPool.sol │ ├── SafeCast.sol │ ├── pools │ │ └── Stake.sol │ ├── LiquidityMath.sol │ ├── Sets.sol │ └── LibFuse.sol ├── CrossChainCanonicalAlchemicTokenV2.sol ├── TransmuterConduit.sol ├── AutoleverageCurveMetapool.sol ├── utils │ └── Whitelist.sol ├── AutoleverageCurveFactoryethpool.sol └── adapters │ └── yearn │ └── YearnTokenAdapter.sol ├── contracts-hardhat ├── test │ ├── TestErc20Receiver.sol │ ├── TestWhitelistedCaller.sol │ ├── TestTransmuter.sol │ ├── TestAlchemicToken.sol │ ├── TestSets.sol │ ├── ERC20Mock.sol │ ├── TestFlashBorrower.sol │ ├── TestWhitelisted.sol │ ├── TransmuterBufferMock.sol │ └── TestYieldTokenAdapter.sol ├── interfaces │ ├── ITransmuterV1.sol │ ├── IALCXSource.sol │ ├── IERC20TokenReceiver.sol │ ├── alchemist │ │ └── IAlchemistV2Immutables.sol │ ├── IERC20Mintable.sol │ ├── external │ │ ├── IProxyAdmin.sol │ │ ├── aave │ │ │ ├── IWethGateway.sol │ │ │ ├── ILendingPoolAddressesProviderRegistry.sol │ │ │ ├── IScaledBalanceToken.sol │ │ │ ├── DataTypes.sol │ │ │ └── ILendingPoolAddressesProvider.sol │ │ ├── IWETH9.sol │ │ └── tether │ │ │ └── ITetherToken.sol │ ├── IAlchemistV2.sol │ ├── IERC20Metadata.sol │ ├── IERC20Burnable.sol │ ├── IAlchemicToken.sol │ ├── IERC3156FlashBorrower.sol │ ├── IMulticall.sol │ ├── IERC20PermitAllowed.sol │ ├── IERC3156FlashLender.sol │ ├── IStakingPools.sol │ ├── test │ │ └── ITestYieldToken.sol │ ├── ITokenAdapter.sol │ ├── IWhitelist.sol │ └── IWETHGateway.sol ├── CrossChainCanonicalGALCX.sol ├── base │ ├── Errors.sol │ ├── Multicall.sol │ ├── Mutex.sol │ └── SelfPermit.sol ├── CrossChainCanonicalAlchemicTokenV2.sol ├── libraries │ ├── SafeCast.sol │ ├── pools │ │ └── Stake.sol │ ├── LiquidityMath.sol │ └── Sets.sol ├── TransmuterConduit.sol ├── utils │ └── Whitelist.sol └── adapters │ └── yearn │ └── YearnTokenAdapter.sol ├── test-forge ├── utils │ ├── users │ │ ├── ThreePoolAssetManagerUser.sol │ │ ├── EthAssetManagerUser.sol │ │ ├── ERC20User.sol │ │ └── SafeERC20User.sol │ └── mocks │ │ └── ERC20Mock.sol ├── mocks │ └── TransmuterBufferMock.sol ├── TransmuterConduit.t.sol ├── RETHAdapterV1.t.sol └── WstETHAdapterV1.t.sol ├── tsconfig.json ├── test-hardhat └── Sets.spec.ts ├── .gitignore ├── package.json └── utils └── helpers.ts /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/C4-banner-7C19B.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].txt_Files/C4-banner-7C19B.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/AlchemixV2_elixir.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/img/AlchemixV2_elixir.jpg -------------------------------------------------------------------------------- /img/AlchemixV2_token_flows.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/img/AlchemixV2_token_flows.jpg -------------------------------------------------------------------------------- /img/AlchemixV2_function_calls.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/img/AlchemixV2_function_calls.jpg -------------------------------------------------------------------------------- /img/AlchemixV2_proxy_configurations.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/img/AlchemixV2_proxy_configurations.jpg -------------------------------------------------------------------------------- /contracts-full/interfaces/ITransmuterV1.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | interface ITransmuterV1 { 5 | function distribute(address origin, uint256 amount) external; 6 | } -------------------------------------------------------------------------------- /contracts-full/test/TestErc20Receiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | contract TestErc20Receiver { 4 | constructor() {} 5 | 6 | function onERC20Received(address underlyingToken, uint256 amount) external {} 7 | } 8 | -------------------------------------------------------------------------------- /contracts-hardhat/test/TestErc20Receiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | contract TestErc20Receiver { 4 | constructor() {} 5 | 6 | function onERC20Received(address underlyingToken, uint256 amount) external {} 7 | } 8 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/3-FB033.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/3-FB033.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/5-E9BDB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/5-E9BDB.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/IMG_9458-C2A76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/IMG_9458-C2A76.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/unknown-9507B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/unknown-9507B.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].txt_Files/IMG_9458-C2A76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].txt_Files/IMG_9458-C2A76.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].txt_Files/unknown-9507B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].txt_Files/unknown-9507B.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/786914635986501654-46CF8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/786914635986501654-46CF8.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/851893826846457866-1AD3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/851893826846457866-1AD3D.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/851893827315826708-F59C0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/851893827315826708-F59C0.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/851893827706028033-9A97C.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/851893827706028033-9A97C.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-italic-400-E988B.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-italic-400-E988B.woff2 -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-italic-500-0777F.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-italic-500-0777F.woff2 -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-italic-600-CB411.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-italic-600-CB411.woff2 -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-italic-700-891AC.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-italic-700-891AC.woff2 -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-italic-800-D36B0.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-italic-800-D36B0.woff2 -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-normal-400-1456D.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-normal-400-1456D.woff2 -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-normal-500-89CE5.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-normal-500-89CE5.woff2 -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-normal-600-C1EA8.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-normal-600-C1EA8.woff2 -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-normal-700-1949A.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-normal-700-1949A.woff2 -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-normal-800-58487.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ggsans-normal-800-58487.woff2 -------------------------------------------------------------------------------- /contracts-full/test/TestWhitelistedCaller.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "./TestWhitelisted.sol"; 4 | 5 | contract TestWhitelistedCaller { 6 | constructor() { 7 | 8 | } 9 | 10 | function test(address target) external { 11 | TestWhitelisted(target).test(); 12 | } 13 | } -------------------------------------------------------------------------------- /contracts-hardhat/test/TestWhitelistedCaller.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "./TestWhitelisted.sol"; 4 | 5 | contract TestWhitelistedCaller { 6 | constructor() { 7 | 8 | } 9 | 10 | function test(address target) external { 11 | TestWhitelisted(target).test(); 12 | } 13 | } -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/2a9faff195fe333526cfe6ae6fce1420-927E9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/2a9faff195fe333526cfe6ae6fce1420-927E9.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/467517ffa947930b8383c77934903657-6CBF8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/467517ffa947930b8383c77934903657-6CBF8.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/58b16f0c-7fca-4180-bec0-a9a1e71e7aa3-04B6A: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/58b16f0c-7fca-4180-bec0-a9a1e71e7aa3-04B6A -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/5960c5502dd09d4875482231f43edbc5-F05FC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/5960c5502dd09d4875482231f43edbc5-F05FC.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/5d12e3b47f1005d10059611eeaf3a79d-E9754.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/5d12e3b47f1005d10059611eeaf3a79d-E9754.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/5f978694dec96afc1640b5426003aef1-3E74E.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/5f978694dec96afc1640b5426003aef1-3E74E.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/60973beb51aebcfc8ef49e01c59da7c1-C5171.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/60973beb51aebcfc8ef49e01c59da7c1-C5171.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/67594ee4b4d1fc03bca468327a0d145b-0C614.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/67594ee4b4d1fc03bca468327a0d145b-0C614.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/9503f567dabd2781b3d25827ceb83075-313E1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/9503f567dabd2781b3d25827ceb83075-313E1.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ae70f07a06c1c7e983291bb14a1bed7f-F1116.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/ae70f07a06c1c7e983291bb14a1bed7f-F1116.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/c9cb30134c634c9e02d0c64df4922803-1AAF2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/c9cb30134c634c9e02d0c64df4922803-1AAF2.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/e30d0fe5b5a56ace70463fe4fb765489-6D670.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/e30d0fe5b5a56ace70463fe4fb765489-6D670.png -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].txt_Files/58b16f0c-7fca-4180-bec0-a9a1e71e7aa3-04B6A: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-423n4/2022-05-alchemix/HEAD/discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].txt_Files/58b16f0c-7fca-4180-bec0-a9a1e71e7aa3-04B6A -------------------------------------------------------------------------------- /contracts-full/interfaces/convex/IConvexBooster.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | interface IConvexBooster { 5 | function deposit(uint256 pid, uint256 amount, bool stake) external returns (bool); 6 | function withdraw(uint256 pid, uint256 amount) external returns (bool); 7 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/ITransmuterV1.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | interface ITransmuterV1 { 5 | function distribute(address origin, uint256 amount) external; 6 | 7 | function migrateFunds(address migrateTo) external; 8 | 9 | function setPause(bool val) external; 10 | } 11 | -------------------------------------------------------------------------------- /contracts-full/test/TestTransmuter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.11; 3 | 4 | contract TestTransmuter { 5 | mapping(address => uint256) public totalExchanged; 6 | 7 | function onERC20Received(address token, uint256 amount) external { 8 | totalExchanged[token] += amount; 9 | } 10 | } -------------------------------------------------------------------------------- /contracts-hardhat/test/TestTransmuter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.11; 3 | 4 | contract TestTransmuter { 5 | mapping(address => uint256) public totalExchanged; 6 | 7 | function onERC20Received(address token, uint256 amount) external { 8 | totalExchanged[token] += amount; 9 | } 10 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/vesper/IVesperRewards.sol: -------------------------------------------------------------------------------- 1 | 2 | // SPDX-License-Identifier: MIT 3 | 4 | pragma solidity >=0.6.12; 5 | 6 | interface IVesperRewards { 7 | function claimReward(address) external; 8 | 9 | function claimable(address) external view returns (address[] memory, uint256[] memory); 10 | 11 | function rewardTokens(uint256) external view returns (address); 12 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/convex/IConvexToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | interface IConvexToken is IERC20 { 7 | function maxSupply() external view returns (uint256); 8 | function totalCliffs() external view returns (uint256); 9 | function reductionPerCliff() external view returns (uint256); 10 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IALCXSource.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.11; 3 | 4 | interface IALCXSource { 5 | function getStakeTotalDeposited(address _user, uint256 _poolId) external view returns (uint256); 6 | function claim(uint256 _poolId) external; 7 | function deposit(uint256 _poolId, uint256 _depositAmount) external; 8 | function withdraw(uint256 _poolId, uint256 _withdrawAmount) external; 9 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IALCXSource.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.11; 3 | 4 | interface IALCXSource { 5 | function getStakeTotalDeposited(address _user, uint256 _poolId) external view returns (uint256); 6 | function claim(uint256 _poolId) external; 7 | function deposit(uint256 _poolId, uint256 _depositAmount) external; 8 | function withdraw(uint256 _poolId, uint256 _withdrawAmount) external; 9 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/lido/IStETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.5.0; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | interface IStETH is IERC20 { 7 | function sharesOf(address account) external view returns (uint256); 8 | function getPooledEthByShares(uint256 sharesAmount) external view returns (uint256); 9 | function submit(address referral) external payable returns (uint256); 10 | } -------------------------------------------------------------------------------- /test-forge/utils/users/ThreePoolAssetManagerUser.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.13; 3 | 4 | import {ThreePoolAssetManager} from "../../../ThreePoolAssetManager.sol"; 5 | 6 | contract ThreePoolAssetManagerUser { 7 | ThreePoolAssetManager internal manager; 8 | 9 | constructor(ThreePoolAssetManager _manager) { manager = _manager; } 10 | 11 | function acceptAdmin() external { 12 | manager.acceptAdmin(); 13 | } 14 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "resolveJsonModule": true, 8 | "outDir": "dist", 9 | "declaration": true, 10 | "noImplicitAny": false 11 | }, 12 | "include": ["./scripts", "./test", "./typechain", "./utils", "./deploy/**/*", 13 | "./integration-test", "./tasks" 14 | ], 15 | "files": ["./hardhat.config.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /contracts-full/interfaces/compound/IInterestRateModel.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.13; 3 | 4 | interface IInterestRateModel { 5 | function getBorrowRate( 6 | uint256, 7 | uint256, 8 | uint256 9 | ) external view returns (uint256); 10 | 11 | function getSupplyRate( 12 | uint256, 13 | uint256, 14 | uint256, 15 | uint256 16 | ) external view returns (uint256); 17 | } -------------------------------------------------------------------------------- /contracts-full/test/TestAlchemicToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "./TestERC20.sol"; 4 | 5 | contract TestAlchemicToken is TestERC20 { 6 | constructor(uint256 amountToMint, uint8 _decimals) TestERC20(amountToMint, _decimals) { 7 | } 8 | 9 | function hasMinted(address account) external view returns (uint256) { 10 | return 0; 11 | } 12 | 13 | function lowerHasMinted(uint256 amount) external { 14 | require(true); 15 | } 16 | } -------------------------------------------------------------------------------- /contracts-hardhat/test/TestAlchemicToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "./TestERC20.sol"; 4 | 5 | contract TestAlchemicToken is TestERC20 { 6 | constructor(uint256 amountToMint, uint8 _decimals) TestERC20(amountToMint, _decimals) { 7 | } 8 | 9 | function hasMinted(address account) external view returns (uint256) { 10 | return 0; 11 | } 12 | 13 | function lowerHasMinted(uint256 amount) external { 14 | require(true); 15 | } 16 | } -------------------------------------------------------------------------------- /test-forge/utils/users/EthAssetManagerUser.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.13; 3 | 4 | import {EthAssetManager} from "../../../EthAssetManager.sol"; 5 | 6 | contract EthAssetManagerUser { 7 | EthAssetManager internal manager; 8 | 9 | constructor(EthAssetManager _manager) { manager = _manager; } 10 | 11 | receive() external payable {} 12 | 13 | function acceptAdmin() external { 14 | manager.acceptAdmin(); 15 | } 16 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IERC20TokenReceiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | /// @title IERC20TokenReceiver 4 | /// @author Alchemix Finance 5 | interface IERC20TokenReceiver { 6 | /// @notice Informs implementors of this interface that an ERC20 token has been transferred. 7 | /// 8 | /// @param token The token that was transferred. 9 | /// @param value The amount of the token that was transferred. 10 | function onERC20Received(address token, uint256 value) external; 11 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IERC20TokenReceiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | /// @title IERC20TokenReceiver 4 | /// @author Alchemix Finance 5 | interface IERC20TokenReceiver { 6 | /// @notice Informs implementors of this interface that an ERC20 token has been transferred. 7 | /// 8 | /// @param token The token that was transferred. 9 | /// @param value The amount of the token that was transferred. 10 | function onERC20Received(address token, uint256 value) external; 11 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/lido/IWstETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.5.0; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | interface IWstETH is IERC20 { 7 | function getWstETHByStETH(uint256 amount) external view returns (uint256); 8 | function getStETHByWstETH(uint256 amount) external view returns (uint256); 9 | function wrap(uint256 amount) external returns (uint256); 10 | function unwrap(uint256 amount) external returns (uint256); 11 | } -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f50d-195C0.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/CrossChainCanonicalGALCX.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.11; 3 | 4 | import {CrossChainCanonicalBase} from "./CrossChainCanonicalBase.sol"; 5 | 6 | contract CrossChainCanonicalGALCX is CrossChainCanonicalBase { 7 | function initialize( 8 | string memory name, 9 | string memory symbol, 10 | address[] memory _bridgeTokens 11 | ) public initializer { 12 | __CrossChainCanonicalBase_init( 13 | name, 14 | symbol, 15 | msg.sender, 16 | _bridgeTokens 17 | ); 18 | } 19 | } -------------------------------------------------------------------------------- /contracts-hardhat/CrossChainCanonicalGALCX.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.11; 3 | 4 | import {CrossChainCanonicalBase} from "./CrossChainCanonicalBase.sol"; 5 | 6 | contract CrossChainCanonicalGALCX is CrossChainCanonicalBase { 7 | function initialize( 8 | string memory name, 9 | string memory symbol, 10 | address[] memory _bridgeTokens 11 | ) public initializer { 12 | __CrossChainCanonicalBase_init( 13 | name, 14 | symbol, 15 | msg.sender, 16 | _bridgeTokens 17 | ); 18 | } 19 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/alchemist/IAlchemistV2Immutables.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | /// @title IAlchemistV2Immutables 4 | /// @author Alchemix Finance 5 | interface IAlchemistV2Immutables { 6 | /// @notice Returns the version of the alchemist. 7 | /// 8 | /// @return The version. 9 | function version() external view returns (string memory); 10 | 11 | /// @notice Returns the address of the debt token used by the system. 12 | /// 13 | /// @return The address of the debt token. 14 | function debtToken() external view returns (address); 15 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/alchemist/IAlchemistV2Immutables.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | /// @title IAlchemistV2Immutables 4 | /// @author Alchemix Finance 5 | interface IAlchemistV2Immutables { 6 | /// @notice Returns the version of the alchemist. 7 | /// 8 | /// @return The version. 9 | function version() external view returns (string memory); 10 | 11 | /// @notice Returns the address of the debt token used by the system. 12 | /// 13 | /// @return The address of the debt token. 14 | function debtToken() external view returns (address); 15 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IERC20Mintable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "./IERC20Minimal.sol"; 4 | 5 | /// @title IERC20Mintable 6 | /// @author Alchemix Finance 7 | interface IERC20Mintable is IERC20Minimal { 8 | /// @notice Mints `amount` tokens to `recipient`. 9 | /// 10 | /// @param recipient The address which will receive the minted tokens. 11 | /// @param amount The amount of tokens to mint. 12 | /// 13 | /// @return If minting the tokens was successful. 14 | function mint(address recipient, uint256 amount) external returns (bool); 15 | } -------------------------------------------------------------------------------- /test-forge/mocks/TransmuterBufferMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.13; 2 | 3 | import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; 4 | import "../../interfaces/IERC20TokenReceiver.sol"; 5 | 6 | contract TransmuterBufferMock is IERC20TokenReceiver { 7 | mapping(address => bool) public underlyingTokens; 8 | constructor(address underlyingToken) { 9 | underlyingTokens[underlyingToken] = true; 10 | } 11 | 12 | function onERC20Received(address underlyingToken, uint256 amount) external override { 13 | require(underlyingTokens[underlyingToken]); 14 | } 15 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IERC20Mintable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "openzeppelin/token/ERC20/IERC20.sol"; 4 | 5 | /// @title IERC20Mintable 6 | /// @author Alchemix Finance 7 | interface IERC20Mintable is IERC20 { 8 | /// @notice Mints `amount` tokens to `recipient`. 9 | /// 10 | /// @param recipient The address which will receive the minted tokens. 11 | /// @param amount The amount of tokens to mint. 12 | /// 13 | /// @return If minting the tokens was successful. 14 | function mint(address recipient, uint256 amount) external returns (bool); 15 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IAaveFlashLoanReceiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | /** 4 | * @title IFlashLoanReceiver interface 5 | * @notice Interface for the Aave fee IFlashLoanReceiver. 6 | * @author Aave 7 | * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract 8 | **/ 9 | interface IAaveFlashLoanReceiver { 10 | function executeOperation( 11 | address[] calldata assets, 12 | uint256[] calldata amounts, 13 | uint256[] calldata premiums, 14 | address initiator, 15 | bytes calldata params 16 | ) external returns (bool); 17 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/external/IProxyAdmin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | interface IProxyAdmin { 6 | function getProxyImplementation(address proxy) external view returns (address); 7 | 8 | function getProxyAdmin(address proxy) external view returns (address); 9 | 10 | function changeProxyAdmin(address proxy, address newAdmin) external; 11 | 12 | function upgrade(address proxy, address implementation) external; 13 | 14 | function upgradeAndCall( 15 | address proxy, 16 | address implementation, 17 | bytes memory data 18 | ) external; 19 | } 20 | -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/external/IProxyAdmin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | interface IProxyAdmin { 6 | function getProxyImplementation(address proxy) external view returns (address); 7 | 8 | function getProxyAdmin(address proxy) external view returns (address); 9 | 10 | function changeProxyAdmin(address proxy, address newAdmin) external; 11 | 12 | function upgrade(address proxy, address implementation) external; 13 | 14 | function upgradeAndCall( 15 | address proxy, 16 | address implementation, 17 | bytes memory data 18 | ) external; 19 | } 20 | -------------------------------------------------------------------------------- /contracts-full/test/TestSets.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "../libraries/Sets.sol"; 4 | 5 | contract TestSets { 6 | using Sets for Sets.AddressSet; 7 | 8 | Sets.AddressSet private testAddys; 9 | 10 | constructor() { 11 | 12 | } 13 | 14 | function add(address val) external { 15 | require(testAddys.add(val), "failed to add"); 16 | } 17 | 18 | function remove(address val) external { 19 | require(testAddys.remove(val), "failed to remove"); 20 | } 21 | 22 | function contains(address val) external view returns (bool) { 23 | return testAddys.contains(val); 24 | } 25 | } -------------------------------------------------------------------------------- /contracts-hardhat/test/TestSets.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "../libraries/Sets.sol"; 4 | 5 | contract TestSets { 6 | using Sets for Sets.AddressSet; 7 | 8 | Sets.AddressSet private testAddys; 9 | 10 | constructor() { 11 | 12 | } 13 | 14 | function add(address val) external { 15 | require(testAddys.add(val), "failed to add"); 16 | } 17 | 18 | function remove(address val) external { 19 | require(testAddys.remove(val), "failed to remove"); 20 | } 21 | 22 | function contains(address val) external view returns (bool) { 23 | return testAddys.contains(val); 24 | } 25 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IAlchemistV2.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "./alchemist/IAlchemistV2Actions.sol"; 4 | import "./alchemist/IAlchemistV2AdminActions.sol"; 5 | import "./alchemist/IAlchemistV2Errors.sol"; 6 | import "./alchemist/IAlchemistV2Immutables.sol"; 7 | import "./alchemist/IAlchemistV2Events.sol"; 8 | import "./alchemist/IAlchemistV2State.sol"; 9 | 10 | /// @title IAlchemistV2 11 | /// @author Alchemix Finance 12 | interface IAlchemistV2 is 13 | IAlchemistV2Actions, 14 | IAlchemistV2AdminActions, 15 | IAlchemistV2Errors, 16 | IAlchemistV2Immutables, 17 | IAlchemistV2Events, 18 | IAlchemistV2State 19 | { } 20 | -------------------------------------------------------------------------------- /contracts-full/base/Errors.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | /// @notice An error used to indicate that an action could not be completed because either the `msg.sender` or 4 | /// `msg.origin` is not authorized. 5 | error Unauthorized(); 6 | 7 | /// @notice An error used to indicate that an action could not be completed because the contract either already existed 8 | /// or entered an illegal condition which is not recoverable from. 9 | error IllegalState(); 10 | 11 | /// @notice An error used to indicate that an action could not be completed because of an illegal argument was passed 12 | /// to the function. 13 | error IllegalArgument(); -------------------------------------------------------------------------------- /contracts-full/libraries/RocketPool.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import {IRETH} from "../interfaces/external/rocket/IRETH.sol"; 4 | import {IRocketStorage} from "../interfaces/external/rocket/IRocketStorage.sol"; 5 | 6 | library RocketPool { 7 | /// @dev Gets the current rETH contract. 8 | /// 9 | /// @param self The rocket storage contract to read from. 10 | /// 11 | /// @return The current rETH contract. 12 | function getRETH(IRocketStorage self) internal view returns (IRETH) { 13 | return IRETH(self.getAddress( 14 | keccak256(abi.encodePacked("contract.address", "rocketTokenRETH")) 15 | )); 16 | } 17 | } -------------------------------------------------------------------------------- /contracts-hardhat/base/Errors.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | /// @notice An error used to indicate that an action could not be completed because either the `msg.sender` or 4 | /// `msg.origin` is not authorized. 5 | error Unauthorized(); 6 | 7 | /// @notice An error used to indicate that an action could not be completed because the contract either already existed 8 | /// or entered an illegal condition which is not recoverable from. 9 | error IllegalState(); 10 | 11 | /// @notice An error used to indicate that an action could not be completed because of an illegal argument was passed 12 | /// to the function. 13 | error IllegalArgument(); -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IAlchemistV2.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "./alchemist/IAlchemistV2Actions.sol"; 4 | import "./alchemist/IAlchemistV2AdminActions.sol"; 5 | import "./alchemist/IAlchemistV2Errors.sol"; 6 | import "./alchemist/IAlchemistV2Immutables.sol"; 7 | import "./alchemist/IAlchemistV2Events.sol"; 8 | import "./alchemist/IAlchemistV2State.sol"; 9 | 10 | /// @title IAlchemistV2 11 | /// @author Alchemix Finance 12 | interface IAlchemistV2 is 13 | IAlchemistV2Actions, 14 | IAlchemistV2AdminActions, 15 | IAlchemistV2Errors, 16 | IAlchemistV2Immutables, 17 | IAlchemistV2Events, 18 | IAlchemistV2State 19 | { } 20 | -------------------------------------------------------------------------------- /contracts-full/interfaces/ICurveFactoryethpool.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | interface ICurveFactoryethpool { 4 | /// @notice Perform an exchange between two underlying coins 5 | /// @dev Index values can be found via the `underlying_coins` public getter method 6 | /// @param i Index value for the underlying coin to send 7 | /// @param j Index valie of the underlying coin to recieve 8 | /// @param dx Amount of `i` being exchanged 9 | /// @param min_dy Minimum amount of `j` to receive 10 | /// @return Actual amount of `j` received 11 | function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external payable returns (uint256); 12 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | /// @title IERC20Metadata 4 | /// @author Alchemix Finance 5 | interface IERC20Metadata { 6 | /// @notice Gets the name of the token. 7 | /// 8 | /// @return The name. 9 | function name() external view returns (string memory); 10 | 11 | /// @notice Gets the symbol of the token. 12 | /// 13 | /// @return The symbol. 14 | function symbol() external view returns (string memory); 15 | 16 | /// @notice Gets the number of decimals that the token has. 17 | /// 18 | /// @return The number of decimals. 19 | function decimals() external view returns (uint8); 20 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | /// @title IERC20Metadata 4 | /// @author Alchemix Finance 5 | interface IERC20Metadata { 6 | /// @notice Gets the name of the token. 7 | /// 8 | /// @return The name. 9 | function name() external view returns (string memory); 10 | 11 | /// @notice Gets the symbol of the token. 12 | /// 13 | /// @return The symbol. 14 | function symbol() external view returns (string memory); 15 | 16 | /// @notice Gets the number of decimals that the token has. 17 | /// 18 | /// @return The number of decimals. 19 | function decimals() external view returns (uint8); 20 | } -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f972-F415D.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/CrossChainCanonicalAlchemicTokenV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.11; 3 | 4 | import {CrossChainCanonicalBase} from "./CrossChainCanonicalBase.sol"; 5 | import {AlchemicTokenV2Base} from "./AlchemicTokenV2Base.sol"; 6 | 7 | contract CrossChainCanonicalAlchemicTokenV2 is CrossChainCanonicalBase, AlchemicTokenV2Base { 8 | function initialize( 9 | string memory name, 10 | string memory symbol, 11 | address[] memory _bridgeTokens 12 | ) public initializer { 13 | __CrossChainCanonicalBase_init( 14 | name, 15 | symbol, 16 | msg.sender, 17 | _bridgeTokens 18 | ); 19 | __AlchemicTokenV2Base_init(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /contracts-hardhat/CrossChainCanonicalAlchemicTokenV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.11; 3 | 4 | import {CrossChainCanonicalBase} from "./CrossChainCanonicalBase.sol"; 5 | import {AlchemicTokenV2Base} from "./AlchemicTokenV2Base.sol"; 6 | 7 | contract CrossChainCanonicalAlchemicTokenV2 is CrossChainCanonicalBase, AlchemicTokenV2Base { 8 | function initialize( 9 | string memory name, 10 | string memory symbol, 11 | address[] memory _bridgeTokens 12 | ) public initializer { 13 | __CrossChainCanonicalBase_init( 14 | name, 15 | symbol, 16 | msg.sender, 17 | _bridgeTokens 18 | ); 19 | __AlchemicTokenV2Base_init(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test-forge/utils/mocks/ERC20Mock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.13; 3 | 4 | import {ERC20} from "openzeppelin/token/ERC20/ERC20.sol"; 5 | 6 | contract ERC20Mock is ERC20 { 7 | uint8 private _decimals; 8 | 9 | constructor(string memory name, string memory symbol, uint8 mockDecimals) ERC20(name, symbol) { 10 | _decimals = mockDecimals; 11 | } 12 | 13 | function decimals() public view override returns (uint8) { 14 | return _decimals; 15 | } 16 | 17 | function burn(address owner, uint256 amount) public { 18 | _burn(owner, amount); 19 | } 20 | 21 | function mint(address receiver, uint256 amount) public { 22 | _mint(receiver, amount); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts-full/interfaces/external/aave/IWethGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | interface IWETHGateway { 5 | function depositETH( 6 | address lendingPool, 7 | address onBehalfOf, 8 | uint16 referralCode 9 | ) external payable; 10 | 11 | function withdrawETH( 12 | address lendingPool, 13 | uint256 amount, 14 | address onBehalfOf 15 | ) external; 16 | 17 | function repayETH( 18 | address lendingPool, 19 | uint256 amount, 20 | uint256 rateMode, 21 | address onBehalfOf 22 | ) external payable; 23 | 24 | function borrowETH( 25 | address lendingPool, 26 | uint256 amount, 27 | uint256 interesRateMode, 28 | uint16 referralCode 29 | ) external; 30 | } 31 | -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/external/aave/IWethGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | interface IWETHGateway { 5 | function depositETH( 6 | address lendingPool, 7 | address onBehalfOf, 8 | uint16 referralCode 9 | ) external payable; 10 | 11 | function withdrawETH( 12 | address lendingPool, 13 | uint256 amount, 14 | address onBehalfOf 15 | ) external; 16 | 17 | function repayETH( 18 | address lendingPool, 19 | uint256 amount, 20 | uint256 rateMode, 21 | address onBehalfOf 22 | ) external payable; 23 | 24 | function borrowETH( 25 | address lendingPool, 26 | uint256 amount, 27 | uint256 interesRateMode, 28 | uint16 referralCode 29 | ) external; 30 | } 31 | -------------------------------------------------------------------------------- /contracts-full/interfaces/external/IWETH9.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "../IERC20Minimal.sol"; 4 | import "../IERC20Metadata.sol"; 5 | 6 | /// @title IWETH9 7 | interface IWETH9 is IERC20Minimal, IERC20Metadata { 8 | /// @notice Deposits `msg.value` ethereum into the contract and mints `msg.value` tokens. 9 | function deposit() external payable; 10 | 11 | /// @notice Burns `amount` tokens to retrieve `amount` ethereum from the contract. 12 | /// 13 | /// @dev This version of WETH utilizes the `transfer` function which hard codes the amount of gas that is allowed 14 | /// to be utilized to be exactly 2300 when receiving ethereum. 15 | /// 16 | /// @param amount The amount of tokens to burn. 17 | function withdraw(uint256 amount) external; 18 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IWETH9.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "openzeppelin/token/ERC20/IERC20.sol"; 4 | 5 | import "../IERC20Metadata.sol"; 6 | 7 | /// @title IWETH9 8 | interface IWETH9 is IERC20, IERC20Metadata { 9 | /// @notice Deposits `msg.value` ethereum into the contract and mints `msg.value` tokens. 10 | function deposit() external payable; 11 | 12 | /// @notice Burns `amount` tokens to retrieve `amount` ethereum from the contract. 13 | /// 14 | /// @dev This version of WETH utilizes the `transfer` function which hard codes the amount of gas 15 | /// that is allowed to be utilized to be exactly 2300 when receiving ethereum. 16 | /// 17 | /// @param amount The amount of tokens to burn. 18 | function withdraw(uint256 amount) external; 19 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/external/IWETH9.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "../IERC20Minimal.sol"; 4 | import "../IERC20Metadata.sol"; 5 | 6 | /// @title IWETH9 7 | interface IWETH9 is IERC20Minimal, IERC20Metadata { 8 | /// @notice Deposits `msg.value` ethereum into the contract and mints `msg.value` tokens. 9 | function deposit() external payable; 10 | 11 | /// @notice Burns `amount` tokens to retrieve `amount` ethereum from the contract. 12 | /// 13 | /// @dev This version of WETH utilizes the `transfer` function which hard codes the amount of gas that is allowed 14 | /// to be utilized to be exactly 2300 when receiving ethereum. 15 | /// 16 | /// @param amount The amount of tokens to burn. 17 | function withdraw(uint256 amount) external; 18 | } -------------------------------------------------------------------------------- /test-forge/utils/users/ERC20User.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.13; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | contract ERC20User { 7 | IERC20 private token; 8 | 9 | constructor(IERC20 _token) { 10 | token = _token; 11 | } 12 | 13 | function approve(address spender, uint256 amount) external returns (bool) { 14 | return token.approve(spender, amount); 15 | } 16 | 17 | function transfer(address receiver, uint256 amount) external returns (bool) { 18 | return token.transfer(receiver, amount); 19 | } 20 | 21 | function transferFrom(address owner, address receiver, uint256 amount) external returns (bool) { 22 | return token.transferFrom(owner, receiver, amount); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IERC20Burnable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "./IERC20Minimal.sol"; 4 | 5 | /// @title IERC20Burnable 6 | /// @author Alchemix Finance 7 | interface IERC20Burnable is IERC20Minimal { 8 | /// @notice Burns `amount` tokens from the balance of `msg.sender`. 9 | /// 10 | /// @param amount The amount of tokens to burn. 11 | /// 12 | /// @return If burning the tokens was successful. 13 | function burn(uint256 amount) external returns (bool); 14 | 15 | /// @notice Burns `amount` tokens from `owner`'s balance. 16 | /// 17 | /// @param owner The address to burn tokens from. 18 | /// @param amount The amount of tokens to burn. 19 | /// 20 | /// @return If burning the tokens was successful. 21 | function burnFrom(address owner, uint256 amount) external returns (bool); 22 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IERC20Burnable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "openzeppelin/token/ERC20/IERC20.sol"; 4 | 5 | /// @title IERC20Burnable 6 | /// @author Alchemix Finance 7 | interface IERC20Burnable is IERC20 { 8 | /// @notice Burns `amount` tokens from the balance of `msg.sender`. 9 | /// 10 | /// @param amount The amount of tokens to burn. 11 | /// 12 | /// @return If burning the tokens was successful. 13 | function burn(uint256 amount) external returns (bool); 14 | 15 | /// @notice Burns `amount` tokens from `owner`'s balance. 16 | /// 17 | /// @param owner The address to burn tokens from. 18 | /// @param amount The amount of tokens to burn. 19 | /// 20 | /// @return If burning the tokens was successful. 21 | function burnFrom(address owner, uint256 amount) external returns (bool); 22 | } -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/solarized-dark.min-BA98F.css: -------------------------------------------------------------------------------- 1 | .hljs{display:block;overflow-x:auto;padding:.5em;background:#002b36;color:#839496}.hljs-comment,.hljs-quote{color:#586e75}.hljs-keyword,.hljs-selector-tag,.hljs-addition{color:#859900}.hljs-number,.hljs-string,.hljs-meta .hljs-meta-string,.hljs-literal,.hljs-doctag,.hljs-regexp{color:#2aa198}.hljs-title,.hljs-section,.hljs-name,.hljs-selector-id,.hljs-selector-class{color:#268bd2}.hljs-attribute,.hljs-attr,.hljs-variable,.hljs-template-variable,.hljs-class .hljs-title,.hljs-type{color:#b58900}.hljs-symbol,.hljs-bullet,.hljs-subst,.hljs-meta,.hljs-meta .hljs-keyword,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-link{color:#cb4b16}.hljs-built_in,.hljs-deletion{color:#dc322f}.hljs-formula{background:#073642}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold} -------------------------------------------------------------------------------- /contracts-full/base/Multicall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity ^0.8.11; 3 | 4 | import "../interfaces/IMulticall.sol"; 5 | 6 | /// @title Multicall 7 | /// @author Uniswap Labs 8 | /// 9 | /// @notice Enables calling multiple methods in a single call to the contract 10 | abstract contract Multicall is IMulticall { 11 | /// @inheritdoc IMulticall 12 | function multicall(bytes[] calldata data) external payable override returns (bytes[] memory results) { 13 | results = new bytes[](data.length); 14 | for (uint256 i = 0; i < data.length; i++) { 15 | (bool success, bytes memory result) = address(this).delegatecall(data[i]); 16 | 17 | if (!success) { 18 | revert MulticallFailed(data[i], result); 19 | } 20 | 21 | results[i] = result; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/rocket/IRETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity >=0.5.0; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | import {IERC20Metadata} from "../../IERC20Metadata.sol"; 7 | 8 | interface IRETH is IERC20, IERC20Metadata { 9 | function getEthValue(uint256 amount) external view returns (uint256); 10 | function getRethValue(uint256 amount) external view returns (uint256); 11 | function getExchangeRate() external view returns (uint256); 12 | function getTotalCollateral() external view returns (uint256); 13 | function getCollateralRate() external view returns (uint256); 14 | function depositExcess() external payable; 15 | function depositExcessCollateral() external; 16 | function mint(uint256 amount, address receiver) external; 17 | function burn(uint256 amount) external; 18 | } -------------------------------------------------------------------------------- /contracts-hardhat/base/Multicall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity ^0.8.11; 3 | 4 | import "../interfaces/IMulticall.sol"; 5 | 6 | /// @title Multicall 7 | /// @author Uniswap Labs 8 | /// 9 | /// @notice Enables calling multiple methods in a single call to the contract 10 | abstract contract Multicall is IMulticall { 11 | /// @inheritdoc IMulticall 12 | function multicall(bytes[] calldata data) external payable override returns (bytes[] memory results) { 13 | results = new bytes[](data.length); 14 | for (uint256 i = 0; i < data.length; i++) { 15 | (bool success, bytes memory result) = address(this).delegatecall(data[i]); 16 | 17 | if (!success) { 18 | revert MulticallFailed(data[i], result); 19 | } 20 | 21 | results[i] = result; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f525-8FE4F.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/interfaces/IAlchemicToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import "./IERC20Burnable.sol"; 5 | import "./IERC20Minimal.sol"; 6 | import "./IERC20Mintable.sol"; 7 | 8 | /// @title IAlchemicToken 9 | /// @author Alchemix Finance 10 | interface IAlchemicToken is IERC20Minimal, IERC20Burnable, IERC20Mintable { 11 | /// @notice Gets the total amount of minted tokens for an account. 12 | /// 13 | /// @param account The address of the account. 14 | /// 15 | /// @return The total minted. 16 | function hasMinted(address account) external view returns (uint256); 17 | 18 | /// @notice Lowers the number of tokens which the `msg.sender` has minted. 19 | /// 20 | /// This reverts if the `msg.sender` is not whitelisted. 21 | /// 22 | /// @param amount The amount to lower the minted amount by. 23 | function lowerHasMinted(uint256 amount) external; 24 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IAlchemicToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import "./IERC20Burnable.sol"; 5 | import "./IERC20Minimal.sol"; 6 | import "./IERC20Mintable.sol"; 7 | 8 | /// @title IAlchemicToken 9 | /// @author Alchemix Finance 10 | interface IAlchemicToken is IERC20Minimal, IERC20Burnable, IERC20Mintable { 11 | /// @notice Gets the total amount of minted tokens for an account. 12 | /// 13 | /// @param account The address of the account. 14 | /// 15 | /// @return The total minted. 16 | function hasMinted(address account) external view returns (uint256); 17 | 18 | /// @notice Lowers the number of tokens which the `msg.sender` has minted. 19 | /// 20 | /// This reverts if the `msg.sender` is not whitelisted. 21 | /// 22 | /// @param amount The amount to lower the minted amount by. 23 | function lowerHasMinted(uint256 amount) external; 24 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/convex/IConvexRewards.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | interface IConvexRewards { 7 | function rewardToken() external view returns (IERC20); 8 | function earned(address account) external view returns (uint256); 9 | function extraRewards(uint256 index) external view returns (address); 10 | function balanceOf(address account) external returns(uint256); 11 | function withdraw(uint256 amount, bool claim) external returns (bool); 12 | function withdrawAndUnwrap(uint256 amount, bool claim) external returns (bool); 13 | function getReward() external returns (bool); 14 | function getReward(address recipient, bool claim) external returns (bool); 15 | function stake(uint256 amount) external returns (bool); 16 | function stakeFor(address account, uint256 amount) external returns (bool); 17 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IERC3156FlashBorrower.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title IERC3156FlashBorrower 5 | /// 6 | /// @dev Interface of the ERC3156 FlashBorrower, as defined by [ERC-3156](https://eips.ethereum.org/EIPS/eip-3156). 7 | interface IERC3156FlashBorrower { 8 | /// @notice Receive a flash loan. 9 | /// 10 | /// @param initiator The initiator of the loan. 11 | /// @param token The loan currency. 12 | /// @param amount The amount of tokens lent. 13 | /// @param fee The additional amount of tokens to repay. 14 | /// @param data Arbitrary data structure, intended to contain user-defined parameters. 15 | /// 16 | /// @return magic The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" 17 | function onFlashLoan( 18 | address initiator, 19 | address token, 20 | uint256 amount, 21 | uint256 fee, 22 | bytes calldata data 23 | ) external returns (bytes32 magic); 24 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IERC3156FlashBorrower.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title IERC3156FlashBorrower 5 | /// 6 | /// @dev Interface of the ERC3156 FlashBorrower, as defined by [ERC-3156](https://eips.ethereum.org/EIPS/eip-3156). 7 | interface IERC3156FlashBorrower { 8 | /// @notice Receive a flash loan. 9 | /// 10 | /// @param initiator The initiator of the loan. 11 | /// @param token The loan currency. 12 | /// @param amount The amount of tokens lent. 13 | /// @param fee The additional amount of tokens to repay. 14 | /// @param data Arbitrary data structure, intended to contain user-defined parameters. 15 | /// 16 | /// @return magic The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" 17 | function onFlashLoan( 18 | address initiator, 19 | address token, 20 | uint256 amount, 21 | uint256 fee, 22 | bytes calldata data 23 | ) external returns (bytes32 magic); 24 | } -------------------------------------------------------------------------------- /contracts-full/libraries/SafeCast.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import {IllegalArgument} from "../base/Errors.sol"; 5 | 6 | /// @title Safe casting methods 7 | /// @notice Contains methods for safely casting between types 8 | library SafeCast { 9 | /// @notice Cast a uint256 to a int256, revert on overflow 10 | /// @param y The uint256 to be casted 11 | /// @return z The casted integer, now type int256 12 | function toInt256(uint256 y) internal pure returns (int256 z) { 13 | if (y >= 2**255) { 14 | revert IllegalArgument(); 15 | } 16 | z = int256(y); 17 | } 18 | 19 | /// @notice Cast a int256 to a uint256, revert on underflow 20 | /// @param y The int256 to be casted 21 | /// @return z The casted integer, now type uint256 22 | function toUint256(int256 y) internal pure returns (uint256 z) { 23 | if (y < 0) { 24 | revert IllegalArgument(); 25 | } 26 | z = uint256(y); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f4dc-AC641.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-hardhat/libraries/SafeCast.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import {IllegalArgument} from "../base/Errors.sol"; 5 | 6 | /// @title Safe casting methods 7 | /// @notice Contains methods for safely casting between types 8 | library SafeCast { 9 | /// @notice Cast a uint256 to a int256, revert on overflow 10 | /// @param y The uint256 to be casted 11 | /// @return z The casted integer, now type int256 12 | function toInt256(uint256 y) internal pure returns (int256 z) { 13 | if (y >= 2**255) { 14 | revert IllegalArgument(); 15 | } 16 | z = int256(y); 17 | } 18 | 19 | /// @notice Cast a int256 to a uint256, revert on underflow 20 | /// @param y The int256 to be casted 21 | /// @return z The casted integer, now type uint256 22 | function toUint256(int256 y) internal pure returns (uint256 z) { 23 | if (y < 0) { 24 | revert IllegalArgument(); 25 | } 26 | z = uint256(y); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f604-BF863.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/test/ERC20Mock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.11; 3 | 4 | import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | 6 | /// @title ERC20Mock 7 | /// 8 | /// @dev A mock of an ERC20 token which lets anyone burn and mint tokens. 9 | contract ERC20Mock is ERC20 { 10 | uint8 public dec; 11 | 12 | constructor( 13 | string memory _name, 14 | string memory _symbol, 15 | uint8 mockDecimals 16 | ) ERC20(_name, _symbol) { 17 | dec = mockDecimals; 18 | } 19 | 20 | function decimals() public view override returns (uint8) { 21 | return dec; 22 | } 23 | 24 | function mint(address _recipient, uint256 _amount) external returns (bool) { 25 | _mint(_recipient, _amount); 26 | return true; 27 | } 28 | 29 | function burn(uint256 _amount) external { 30 | _burn(msg.sender, _amount); 31 | } 32 | 33 | function burn(address _account, uint256 _amount) external { 34 | _burn(_account, _amount); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /contracts-hardhat/test/ERC20Mock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.11; 3 | 4 | import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | 6 | /// @title ERC20Mock 7 | /// 8 | /// @dev A mock of an ERC20 token which lets anyone burn and mint tokens. 9 | contract ERC20Mock is ERC20 { 10 | uint8 public dec; 11 | 12 | constructor( 13 | string memory _name, 14 | string memory _symbol, 15 | uint8 mockDecimals 16 | ) ERC20(_name, _symbol) { 17 | dec = mockDecimals; 18 | } 19 | 20 | function decimals() public view override returns (uint8) { 21 | return dec; 22 | } 23 | 24 | function mint(address _recipient, uint256 _amount) external returns (bool) { 25 | _mint(_recipient, _amount); 26 | return true; 27 | } 28 | 29 | function burn(uint256 _amount) external { 30 | _burn(msg.sender, _amount); 31 | } 32 | 33 | function burn(address _account, uint256 _amount) external { 34 | _burn(_account, _amount); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /contracts-full/test/TestFlashBorrower.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "../interfaces/IERC3156FlashLender.sol"; 4 | import "../interfaces/IERC3156FlashBorrower.sol"; 5 | import "../interfaces/IERC20Minimal.sol"; 6 | 7 | contract TestFlashBorrower { 8 | bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); 9 | 10 | constructor() {} 11 | 12 | function takeLoan( 13 | address flashLender, 14 | address token, 15 | uint256 amount 16 | ) external { 17 | uint256 fee = IERC3156FlashLender(flashLender).flashFee(flashLender, amount); 18 | IERC20Minimal(token).approve(flashLender, amount + fee); 19 | IERC3156FlashLender(flashLender).flashLoan(IERC3156FlashBorrower(address(this)), token, amount, bytes("")); 20 | } 21 | 22 | function onFlashLoan( 23 | address from, 24 | address token, 25 | uint256 amount, 26 | uint256 fee, 27 | bytes calldata data 28 | ) external returns (bytes32) { 29 | return CALLBACK_SUCCESS; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts-hardhat/test/TestFlashBorrower.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "../interfaces/IERC3156FlashLender.sol"; 4 | import "../interfaces/IERC3156FlashBorrower.sol"; 5 | import "../interfaces/IERC20Minimal.sol"; 6 | 7 | contract TestFlashBorrower { 8 | bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); 9 | 10 | constructor() {} 11 | 12 | function takeLoan( 13 | address flashLender, 14 | address token, 15 | uint256 amount 16 | ) external { 17 | uint256 fee = IERC3156FlashLender(flashLender).flashFee(flashLender, amount); 18 | IERC20Minimal(token).approve(flashLender, amount + fee); 19 | IERC3156FlashLender(flashLender).flashLoan(IERC3156FlashBorrower(address(this)), token, amount, bytes("")); 20 | } 21 | 22 | function onFlashLoan( 23 | address from, 24 | address token, 25 | uint256 amount, 26 | uint256 fee, 27 | bytes calldata data 28 | ) external returns (bytes32) { 29 | return CALLBACK_SUCCESS; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts-full/interfaces/IMulticall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Multicall interface 5 | /// @author Uniswap Labs 6 | /// 7 | /// @notice Enables calling multiple methods in a single call to the contract. 8 | /// @dev The use of `msg.value` should be heavily scrutinized for implementors of this interfaces. 9 | interface IMulticall { 10 | /// @notice An error used to indicate that an individual call in a multicall failed. 11 | /// 12 | /// @param data The call data. 13 | /// @param result The result of the call. 14 | error MulticallFailed(bytes data, bytes result); 15 | 16 | /// @notice Call multiple functions in the implementing contract. 17 | /// 18 | /// @param data The encoded function data for each of the calls to make to this contract. 19 | /// 20 | /// @return results The results from each of the calls passed in via data. 21 | function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); 22 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IMulticall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title Multicall interface 5 | /// @author Uniswap Labs 6 | /// 7 | /// @notice Enables calling multiple methods in a single call to the contract. 8 | /// @dev The use of `msg.value` should be heavily scrutinized for implementors of this interfaces. 9 | interface IMulticall { 10 | /// @notice An error used to indicate that an individual call in a multicall failed. 11 | /// 12 | /// @param data The call data. 13 | /// @param result The result of the call. 14 | error MulticallFailed(bytes data, bytes result); 15 | 16 | /// @notice Call multiple functions in the implementing contract. 17 | /// 18 | /// @param data The encoded function data for each of the calls to make to this contract. 19 | /// 20 | /// @return results The results from each of the calls passed in via data. 21 | function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); 22 | } -------------------------------------------------------------------------------- /test-forge/utils/users/SafeERC20User.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.13; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | import {SafeERC20} from "../../../libraries/SafeERC20.sol"; 7 | 8 | contract SafeERC20User { 9 | IERC20 public token; 10 | 11 | constructor(IERC20 _token) { 12 | token = _token; 13 | } 14 | 15 | function expectDecimals(address _token) external view returns (uint256) { 16 | return SafeERC20.expectDecimals(_token); 17 | } 18 | 19 | function safeApprove(address spender, uint256 value) external { 20 | SafeERC20.safeApprove(address(token), spender, value); 21 | } 22 | 23 | function safeTransfer(address receiver, uint256 amount) external { 24 | SafeERC20.safeTransfer(address(token), receiver, amount); 25 | } 26 | 27 | function safeTransferFrom( 28 | address owner, 29 | address receiver, 30 | uint256 amount 31 | ) external { 32 | SafeERC20.safeTransferFrom(address(token), owner, receiver, amount); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f606-BE94E.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/interfaces/external/aave/ILendingPoolAddressesProviderRegistry.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title ILendingPoolAddressesProviderRegistry 5 | /// @author Aave 6 | /// 7 | /// @dev Main registry of LendingPoolAddressesProvider of multiple Aave protocol's markets. 8 | /// 9 | /// - Used for indexing purposes of Aave protocol's markets. 10 | /// - The id assigned to a LendingPoolAddressesProvider refers to the market it is connected with, 11 | /// for example with `0` for the Aave main market and `1` for the next created. 12 | interface ILendingPoolAddressesProviderRegistry { 13 | event AddressesProviderRegistered(address indexed newAddress); 14 | event AddressesProviderUnregistered(address indexed newAddress); 15 | 16 | function getAddressesProvidersList() external view returns (address[] memory); 17 | 18 | function getAddressesProviderIdByAddress(address addressesProvider) external view returns (uint256); 19 | 20 | function registerAddressesProvider(address provider, uint256 id) external; 21 | 22 | function unregisterAddressesProvider(address provider) external; 23 | } 24 | -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/external/aave/ILendingPoolAddressesProviderRegistry.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title ILendingPoolAddressesProviderRegistry 5 | /// @author Aave 6 | /// 7 | /// @dev Main registry of LendingPoolAddressesProvider of multiple Aave protocol's markets. 8 | /// 9 | /// - Used for indexing purposes of Aave protocol's markets. 10 | /// - The id assigned to a LendingPoolAddressesProvider refers to the market it is connected with, 11 | /// for example with `0` for the Aave main market and `1` for the next created. 12 | interface ILendingPoolAddressesProviderRegistry { 13 | event AddressesProviderRegistered(address indexed newAddress); 14 | event AddressesProviderUnregistered(address indexed newAddress); 15 | 16 | function getAddressesProvidersList() external view returns (address[] memory); 17 | 18 | function getAddressesProviderIdByAddress(address addressesProvider) external view returns (uint256); 19 | 20 | function registerAddressesProvider(address provider, uint256 id) external; 21 | 22 | function unregisterAddressesProvider(address provider) external; 23 | } 24 | -------------------------------------------------------------------------------- /contracts-full/test/TestWhitelisted.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "@openzeppelin/contracts/access/AccessControl.sol"; 4 | 5 | import { Unauthorized } from "../base/Errors.sol"; 6 | 7 | import "../utils/Whitelist.sol"; 8 | import "../interfaces/IWhitelist.sol"; 9 | 10 | contract TestWhitelisted is AccessControl { 11 | event Success(); 12 | 13 | bytes32 public constant ADMIN = keccak256("ADMIN"); 14 | address public whitelist; 15 | 16 | constructor(address _whitelist) { 17 | _setupRole(ADMIN, msg.sender); 18 | _setRoleAdmin(ADMIN, ADMIN); 19 | whitelist = _whitelist; 20 | } 21 | 22 | function test() external { 23 | // Check if the message sender is an EOA. In the future, this potentially may break. It is important that 24 | // functions which rely on the whitelist not be explicitly vulnerable in the situation where this no longer 25 | // holds true. 26 | if (tx.origin != msg.sender) { 27 | // Only check the whitelist for calls from contracts. 28 | if (!IWhitelist(whitelist).isWhitelisted(msg.sender)) { 29 | revert Unauthorized(); 30 | } 31 | } 32 | emit Success(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts-hardhat/test/TestWhitelisted.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "@openzeppelin/contracts/access/AccessControl.sol"; 4 | 5 | import { Unauthorized } from "../base/Errors.sol"; 6 | 7 | import "../utils/Whitelist.sol"; 8 | import "../interfaces/IWhitelist.sol"; 9 | 10 | contract TestWhitelisted is AccessControl { 11 | event Success(); 12 | 13 | bytes32 public constant ADMIN = keccak256("ADMIN"); 14 | address public whitelist; 15 | 16 | constructor(address _whitelist) { 17 | _setupRole(ADMIN, msg.sender); 18 | _setRoleAdmin(ADMIN, ADMIN); 19 | whitelist = _whitelist; 20 | } 21 | 22 | function test() external { 23 | // Check if the message sender is an EOA. In the future, this potentially may break. It is important that 24 | // functions which rely on the whitelist not be explicitly vulnerable in the situation where this no longer 25 | // holds true. 26 | if (tx.origin != msg.sender) { 27 | // Only check the whitelist for calls from contracts. 28 | if (!IWhitelist(whitelist).isWhitelisted(msg.sender)) { 29 | revert Unauthorized(); 30 | } 31 | } 32 | emit Success(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f6a8-A8AB3.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/test/TransmuterBufferMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.11; 3 | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 5 | import { ITransmuterV2 } from "../interfaces/transmuter/ITransmuterV2.sol"; 6 | 7 | contract TransmuterBufferMock { 8 | using SafeERC20 for IERC20; 9 | 10 | mapping(address => address) public transmuters; 11 | 12 | constructor() {} 13 | 14 | function initialize(address[] calldata _underlyingTokens, address[] calldata _transmuters) external { 15 | for (uint256 i = 0; i < _underlyingTokens.length; i++) { 16 | transmuters[_underlyingTokens[i]] = _transmuters[i]; 17 | } 18 | } 19 | 20 | function exchange(address underlyingToken, uint256 amount) external { 21 | IERC20(underlyingToken).safeTransferFrom(msg.sender, address(this), amount); 22 | ITransmuterV2(transmuters[underlyingToken]).exchange(amount); 23 | } 24 | 25 | function withdraw( 26 | address underlyingToken, 27 | uint256 amount, 28 | address recipient 29 | ) external { 30 | IERC20(underlyingToken).safeTransfer(recipient, amount); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /contracts-hardhat/test/TransmuterBufferMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.11; 3 | import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 5 | import { ITransmuterV2 } from "../interfaces/transmuter/ITransmuterV2.sol"; 6 | 7 | contract TransmuterBufferMock { 8 | using SafeERC20 for IERC20; 9 | 10 | mapping(address => address) public transmuters; 11 | 12 | constructor() {} 13 | 14 | function initialize(address[] calldata _underlyingTokens, address[] calldata _transmuters) external { 15 | for (uint256 i = 0; i < _underlyingTokens.length; i++) { 16 | transmuters[_underlyingTokens[i]] = _transmuters[i]; 17 | } 18 | } 19 | 20 | function exchange(address underlyingToken, uint256 amount) external { 21 | IERC20(underlyingToken).safeTransferFrom(msg.sender, address(this), amount); 22 | ITransmuterV2(transmuters[underlyingToken]).exchange(amount); 23 | } 24 | 25 | function withdraw( 26 | address underlyingToken, 27 | uint256 amount, 28 | address recipient 29 | ) external { 30 | IERC20(underlyingToken).safeTransfer(recipient, amount); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /contracts-full/interfaces/external/aave/IScaledBalanceToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | interface IScaledBalanceToken { 5 | /// @dev Returns the scaled balance of the user. The scaled balance is the sum of all the updated stored balance 6 | /// divided by the reserve's liquidity index at the moment of the update. 7 | /// 8 | /// @param user The user whose balance is calculated. 9 | /// 10 | /// @return The scaled balance of the user. 11 | function scaledBalanceOf(address user) external view returns (uint256); 12 | 13 | /// @dev Returns the scaled balance of the user and the scaled total supply. 14 | /// 15 | /// @param user The address of the user. 16 | /// 17 | /// @return scaledBalance The scaled balance of the user. 18 | /// @return scaledTotalSupply The scaled balance and the scaled total supply. 19 | function getScaledUserBalanceAndSupply(address user) 20 | external view 21 | returns ( 22 | uint256 scaledBalance, 23 | uint256 scaledTotalSupply 24 | ); 25 | 26 | /// @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index). 27 | /// 28 | /// @return The scaled total supply. 29 | function scaledTotalSupply() external view returns (uint256); 30 | } 31 | -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/external/aave/IScaledBalanceToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | interface IScaledBalanceToken { 5 | /// @dev Returns the scaled balance of the user. The scaled balance is the sum of all the updated stored balance 6 | /// divided by the reserve's liquidity index at the moment of the update. 7 | /// 8 | /// @param user The user whose balance is calculated. 9 | /// 10 | /// @return The scaled balance of the user. 11 | function scaledBalanceOf(address user) external view returns (uint256); 12 | 13 | /// @dev Returns the scaled balance of the user and the scaled total supply. 14 | /// 15 | /// @param user The address of the user. 16 | /// 17 | /// @return scaledBalance The scaled balance of the user. 18 | /// @return scaledTotalSupply The scaled balance and the scaled total supply. 19 | function getScaledUserBalanceAndSupply(address user) 20 | external view 21 | returns ( 22 | uint256 scaledBalance, 23 | uint256 scaledTotalSupply 24 | ); 25 | 26 | /// @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index). 27 | /// 28 | /// @return The scaled total supply. 29 | function scaledTotalSupply() external view returns (uint256); 30 | } 31 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f3c6-621A1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f9d1-5BC80.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-hardhat/TransmuterConduit.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "./interfaces/ITransmuterV1.sol"; 4 | import "./interfaces/IERC20TokenReceiver.sol"; 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 7 | import "./base/Errors.sol"; 8 | 9 | contract TransmuterConduit { 10 | using SafeERC20 for IERC20; 11 | 12 | /// @notice The address of the underlying token that is being transmuted. 13 | address public token; 14 | 15 | /// @notice The address of the transmuter to pull funds from. 16 | address public sourceTransmuter; 17 | 18 | /// @notice The address of the transmuter to send funds to;. 19 | address public sinkTransmuter; 20 | 21 | constructor( 22 | address _token, 23 | address _source, 24 | address _sink 25 | ) { 26 | token = _token; 27 | sourceTransmuter = _source; 28 | sinkTransmuter = _sink; 29 | } 30 | 31 | modifier onlySource() { 32 | if (msg.sender != sourceTransmuter) { 33 | revert Unauthorized(); 34 | } 35 | _; 36 | } 37 | 38 | function distribute(address origin, uint256 amount) external onlySource { 39 | IERC20(token).safeTransferFrom(origin, sinkTransmuter, amount); 40 | IERC20TokenReceiver(sinkTransmuter).onERC20Received(token, amount); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /contracts-full/TransmuterConduit.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.13; 2 | 3 | import "./interfaces/ITransmuterV1.sol"; 4 | import "./interfaces/IERC20TokenReceiver.sol"; 5 | import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; 6 | import "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; 7 | import "./base/Errors.sol"; 8 | 9 | contract TransmuterConduit { 10 | using SafeERC20 for IERC20; 11 | 12 | /// @notice The address of the underlying token that is being transmuted. 13 | address public token; 14 | 15 | /// @notice The address of the transmuter to pull funds from. 16 | address public sourceTransmuter; 17 | 18 | /// @notice The address of the transmuter to send funds to;. 19 | address public sinkTransmuter; 20 | 21 | constructor(address _token, address _source, address _sink) { 22 | token = _token; 23 | sourceTransmuter = _source; 24 | sinkTransmuter = _sink; 25 | } 26 | 27 | modifier onlySource() { 28 | if (msg.sender != sourceTransmuter) { 29 | revert Unauthorized("TransmuterConduit"); 30 | } 31 | _; 32 | } 33 | 34 | function distribute(address origin, uint256 amount) external onlySource() { 35 | IERC20(token).safeTransferFrom(origin, sinkTransmuter, amount); 36 | IERC20TokenReceiver(sinkTransmuter).onERC20Received(token, amount); 37 | } 38 | } -------------------------------------------------------------------------------- /contracts-full/base/Mutex.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity ^0.8.11; 3 | 4 | /// @title Mutex 5 | /// @author Alchemix Finance 6 | /// 7 | /// @notice Provides a mutual exclusion lock for implementing contracts. 8 | abstract contract Mutex { 9 | /// @notice An error which is thrown when a lock is attempted to be claimed before it has been freed. 10 | error LockAlreadyClaimed(); 11 | 12 | /// @notice The lock state. Non-zero values indicate the lock has been claimed. 13 | uint256 private _lockState; 14 | 15 | /// @dev A modifier which acquires the mutex. 16 | modifier lock() { 17 | _claimLock(); 18 | 19 | _; 20 | 21 | _freeLock(); 22 | } 23 | 24 | /// @dev Gets if the mutex is locked. 25 | /// 26 | /// @return if the mutex is locked. 27 | function _isLocked() internal returns (bool) { 28 | return _lockState == 1; 29 | } 30 | 31 | /// @dev Claims the lock. If the lock is already claimed, then this will revert. 32 | function _claimLock() internal { 33 | // Check that the lock has not been claimed yet. 34 | if (_lockState != 0) { 35 | revert LockAlreadyClaimed(); 36 | } 37 | 38 | // Claim the lock. 39 | _lockState = 1; 40 | } 41 | 42 | /// @dev Frees the lock. 43 | function _freeLock() internal { 44 | _lockState = 0; 45 | } 46 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/external/tether/ITetherToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "../../IERC20Minimal.sol"; 4 | import "../../IERC20Metadata.sol"; 5 | 6 | /// @title ITetherToken 7 | interface ITetherToken is IERC20Minimal, IERC20Metadata { 8 | // @notice Deprecate current contract in favour of a new one. 9 | function deprecate(address _upgradedAddress) external; 10 | 11 | /// @notice Issue a new amount of tokens. 12 | /// 13 | /// These tokens are deposited into the owner address. 14 | /// 15 | /// @param amount Number of tokens to be issued. 16 | function issue(uint256 amount) external; 17 | 18 | /// @notice Redeem tokens. 19 | /// 20 | /// These tokens are withdrawn from the owner address if the balance must be enough to cover the redeem or the call 21 | /// will fail. 22 | /// 23 | /// @param amount Number of tokens to be issued. 24 | function redeem(uint256 amount) external; 25 | 26 | function setParams(uint256 newBasisPoints, uint256 newMaxFee) external; 27 | 28 | // @notice Emitted when new token are issued. 29 | event Issue(uint256 amount); 30 | 31 | // @notice Emitted when tokens are redeemed. 32 | event Redeem(uint256 amount); 33 | 34 | // @notice Emitted when contract is deprecated. 35 | event Deprecate(address newAddress); 36 | 37 | // @notice Emitted if contract ever adds fees. 38 | event Params(uint256 feeBasisPoints, uint256 maxFee); 39 | } 40 | -------------------------------------------------------------------------------- /contracts-hardhat/base/Mutex.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity ^0.8.11; 3 | 4 | /// @title Mutex 5 | /// @author Alchemix Finance 6 | /// 7 | /// @notice Provides a mutual exclusion lock for implementing contracts. 8 | abstract contract Mutex { 9 | /// @notice An error which is thrown when a lock is attempted to be claimed before it has been freed. 10 | error LockAlreadyClaimed(); 11 | 12 | /// @notice The lock state. Non-zero values indicate the lock has been claimed. 13 | uint256 private _lockState; 14 | 15 | /// @dev A modifier which acquires the mutex. 16 | modifier lock() { 17 | _claimLock(); 18 | 19 | _; 20 | 21 | _freeLock(); 22 | } 23 | 24 | /// @dev Gets if the mutex is locked. 25 | /// 26 | /// @return if the mutex is locked. 27 | function _isLocked() internal returns (bool) { 28 | return _lockState == 1; 29 | } 30 | 31 | /// @dev Claims the lock. If the lock is already claimed, then this will revert. 32 | function _claimLock() internal { 33 | // Check that the lock has not been claimed yet. 34 | if (_lockState != 0) { 35 | revert LockAlreadyClaimed(); 36 | } 37 | 38 | // Claim the lock. 39 | _lockState = 1; 40 | } 41 | 42 | /// @dev Frees the lock. 43 | function _freeLock() internal { 44 | _lockState = 0; 45 | } 46 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/external/tether/ITetherToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "../../IERC20Minimal.sol"; 4 | import "../../IERC20Metadata.sol"; 5 | 6 | /// @title ITetherToken 7 | interface ITetherToken is IERC20Minimal, IERC20Metadata { 8 | // @notice Deprecate current contract in favour of a new one. 9 | function deprecate(address _upgradedAddress) external; 10 | 11 | /// @notice Issue a new amount of tokens. 12 | /// 13 | /// These tokens are deposited into the owner address. 14 | /// 15 | /// @param amount Number of tokens to be issued. 16 | function issue(uint256 amount) external; 17 | 18 | /// @notice Redeem tokens. 19 | /// 20 | /// These tokens are withdrawn from the owner address if the balance must be enough to cover the redeem or the call 21 | /// will fail. 22 | /// 23 | /// @param amount Number of tokens to be issued. 24 | function redeem(uint256 amount) external; 25 | 26 | function setParams(uint256 newBasisPoints, uint256 newMaxFee) external; 27 | 28 | // @notice Emitted when new token are issued. 29 | event Issue(uint256 amount); 30 | 31 | // @notice Emitted when tokens are redeemed. 32 | event Redeem(uint256 amount); 33 | 34 | // @notice Emitted when contract is deprecated. 35 | event Deprecate(address newAddress); 36 | 37 | // @notice Emitted if contract ever adds fees. 38 | event Params(uint256 feeBasisPoints, uint256 maxFee); 39 | } 40 | -------------------------------------------------------------------------------- /contracts-full/interfaces/IERC20PermitAllowed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title IERC20PermitAllowed 5 | /// @author Uniswap Labs 6 | /// 7 | /// @notice Interface used by DAI/CHAI for permit. 8 | interface IERC20PermitAllowed { 9 | /// @notice Approve the spender to spend some tokens via the holder signature. 10 | /// 11 | /// @dev This is the permit interface used by DAI and CHAI. 12 | /// 13 | /// @param holder The address of the token holder, the token owner. 14 | /// @param spender The address of the token spender. 15 | /// @param nonce The holder's nonce, increases at each call to permit. 16 | /// @param expiry The timestamp at which the permit is no longer valid. 17 | /// @param allowed Boolean that sets approval amount, true for type(uint256).max and false for 0. 18 | /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`. 19 | /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`. 20 | /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`. 21 | function permit( 22 | address holder, 23 | address spender, 24 | uint256 nonce, 25 | uint256 expiry, 26 | bool allowed, 27 | uint8 v, 28 | bytes32 r, 29 | bytes32 s 30 | ) external; 31 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IERC20PermitAllowed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title IERC20PermitAllowed 5 | /// @author Uniswap Labs 6 | /// 7 | /// @notice Interface used by DAI/CHAI for permit. 8 | interface IERC20PermitAllowed { 9 | /// @notice Approve the spender to spend some tokens via the holder signature. 10 | /// 11 | /// @dev This is the permit interface used by DAI and CHAI. 12 | /// 13 | /// @param holder The address of the token holder, the token owner. 14 | /// @param spender The address of the token spender. 15 | /// @param nonce The holder's nonce, increases at each call to permit. 16 | /// @param expiry The timestamp at which the permit is no longer valid. 17 | /// @param allowed Boolean that sets approval amount, true for type(uint256).max and false for 0. 18 | /// @param v Must produce valid secp256k1 signature from the holder along with `r` and `s`. 19 | /// @param r Must produce valid secp256k1 signature from the holder along with `v` and `s`. 20 | /// @param s Must produce valid secp256k1 signature from the holder along with `r` and `v`. 21 | function permit( 22 | address holder, 23 | address spender, 24 | uint256 nonce, 25 | uint256 expiry, 26 | bool allowed, 27 | uint8 v, 28 | bytes32 r, 29 | bytes32 s 30 | ) external; 31 | } -------------------------------------------------------------------------------- /contracts-full/AutoleverageCurveMetapool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.11; 3 | 4 | import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; 5 | 6 | import {ICurveMetapool} from "./interfaces/ICurveMetapool.sol"; 7 | 8 | import {AutoleverageBase} from "./AutoleverageBase.sol"; 9 | 10 | /// @title A zapper for leveraged deposits into the Alchemist 11 | contract AutoleverageCurveMetapool is AutoleverageBase { 12 | 13 | /// @inheritdoc AutoleverageBase 14 | function _transferTokensToSelf(address underlyingToken, uint256 collateralInitial) internal override { 15 | if (msg.value > 0) revert IllegalArgument("msg.value should be 0"); 16 | IERC20(underlyingToken).transferFrom(msg.sender, address(this), collateralInitial); 17 | } 18 | 19 | /// @inheritdoc AutoleverageBase 20 | function _maybeConvertCurveOutput(uint256 amountOut) internal override {} 21 | 22 | /// @inheritdoc AutoleverageBase 23 | function _curveSwap(address poolAddress, address debtToken, int128 i, int128 j, uint256 minAmountOut) internal override returns (uint256 amountOut) { 24 | // Curve swap 25 | uint256 debtTokenBalance = IERC20(debtToken).balanceOf(address(this)); 26 | approve(debtToken, poolAddress); 27 | return ICurveMetapool(poolAddress).exchange_underlying( 28 | i, 29 | j, 30 | debtTokenBalance, 31 | minAmountOut 32 | ); 33 | } 34 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/ICurveMetapool.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | interface ICurveMetapool { 4 | /// @notice Perform an exchange between two underlying coins 5 | /// @dev Index values can be found via the `underlying_coins` public getter method 6 | /// @param i Index value for the underlying coin to send 7 | /// @param j Index valie of the underlying coin to recieve 8 | /// @param dx Amount of `i` being exchanged 9 | /// @param min_dy Minimum amount of `j` to receive 10 | /// @return Actual amount of `j` received 11 | function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 min_dy) external returns (uint256); 12 | } 13 | 14 | // interface ICurve { 15 | // function coins(uint256 i) external view returns (address); 16 | // function get_virtual_price() external view returns (uint256); 17 | // function calc_token_amount(uint256[] memory amounts, bool deposit) external view returns (uint256); 18 | // function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external view returns (uint256); 19 | // function fee() external view returns (uint256); 20 | // function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256); 21 | // function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external; 22 | // function add_liquidity(uint256[] memory amounts, uint256 min_mint_amount) external; 23 | // function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_amount) external; 24 | // } -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/2696-15F4A.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f64f-22B8D.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/interfaces/curve/IStableSwap2Pool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.5.0; 3 | 4 | uint256 constant N_COINS = 2; 5 | 6 | interface IStableSwap2Pool { 7 | function coins(uint256 index) external view returns (address); 8 | 9 | function A() external view returns (uint256); 10 | 11 | function get_virtual_price() external view returns (uint256); 12 | 13 | function calc_token_amount( 14 | uint256[N_COINS] calldata amounts, 15 | bool deposit 16 | ) external view returns (uint256 amount); 17 | 18 | function add_liquidity(uint256[N_COINS] calldata amounts, uint256 minimumMintAmount) external; 19 | 20 | function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy); 21 | 22 | function get_dy_underlying(int128 i, int128 j, uint256 dx) external view returns (uint256 dy); 23 | 24 | function exchange( 25 | int128 i, 26 | int128 j, 27 | uint256 dx, 28 | uint256 minimumDy 29 | ) external payable returns (uint256); 30 | 31 | function remove_liquidity(uint256 amount, uint256[N_COINS] calldata minimumAmounts) external; 32 | 33 | function remove_liquidity_imbalance( 34 | uint256[N_COINS] calldata amounts, 35 | uint256 maximumBurnAmount 36 | ) external; 37 | 38 | function calc_withdraw_one_coin(uint256 tokenAmount, int128 i) external view returns (uint256); 39 | 40 | function remove_liquidity_one_coin( 41 | uint256 tokenAmount, 42 | int128 i, 43 | uint256 minimumAmount 44 | ) external; 45 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/curve/IStableSwap3Pool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.5.0; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | uint256 constant N_COINS = 3; 7 | 8 | interface IStableSwap3Pool { 9 | function coins(uint256 index) external view returns (IERC20); 10 | 11 | function A() external view returns (uint256); 12 | 13 | function get_virtual_price() external view returns (uint256); 14 | 15 | function calc_token_amount( 16 | uint256[N_COINS] calldata amounts, 17 | bool deposit 18 | ) external view returns (uint256 amount); 19 | 20 | function add_liquidity(uint256[N_COINS] calldata amounts, uint256 minimumMintAmount) external; 21 | 22 | function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy); 23 | 24 | function get_dy_underlying(int128 i, int128 j, uint256 dx) external view returns (uint256 dy); 25 | 26 | function exchange(int128 i, int128 j, uint256 dx, uint256 minimumDy) external returns (uint256); 27 | 28 | function remove_liquidity(uint256 amount, uint256[N_COINS] calldata minimumAmounts) external; 29 | 30 | function remove_liquidity_imbalance( 31 | uint256[N_COINS] calldata amounts, 32 | uint256 maximumBurnAmount 33 | ) external; 34 | 35 | function calc_withdraw_one_coin(uint256 tokenAmount, int128 i) external view returns (uint256); 36 | 37 | function remove_liquidity_one_coin( 38 | uint256 tokenAmount, 39 | int128 i, 40 | uint256 minimumAmount 41 | ) external; 42 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IERC3156FlashLender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.0; 3 | 4 | import "./IERC3156FlashBorrower.sol"; 5 | 6 | /// @title IERC3156FlashLender 7 | /// 8 | /// @dev Interface of the ERC3156 FlashLender, as defined by [ERC-3156](https://eips.ethereum.org/EIPS/eip-3156). 9 | interface IERC3156FlashLender { 10 | /// @notice The amount of currency available to be lent out. 11 | /// 12 | /// @param token The loan currency. 13 | /// 14 | /// @return amount The amount of `token` that can be borrowed. 15 | function maxFlashLoan(address token) external view returns (uint256 amount); 16 | 17 | /// @notice The fee to be charged for a given loan. 18 | /// 19 | /// @param token The loan currency. 20 | /// @param amount The amount of tokens lent. 21 | /// 22 | /// @return fee The amount of token to be charged for the loan, on top of the returned principal. 23 | function flashFee(address token, uint256 amount) external view returns (uint256 fee); 24 | 25 | /// @notice Initiate a flash loan. 26 | /// 27 | /// @param receiver The receiver of the tokens in the loan and the receiver of the callback. 28 | /// @param token The loan currency. 29 | /// @param amount The amount of tokens lent. 30 | /// @param data Arbitrary data structure, intended to contain user-defined parameters. 31 | /// 32 | /// @return success If the flash loan was successful. 33 | function flashLoan( 34 | IERC3156FlashBorrower receiver, 35 | address token, 36 | uint256 amount, 37 | bytes calldata data 38 | ) external returns (bool success); 39 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IERC3156FlashLender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.5.0; 3 | 4 | import "./IERC3156FlashBorrower.sol"; 5 | 6 | /// @title IERC3156FlashLender 7 | /// 8 | /// @dev Interface of the ERC3156 FlashLender, as defined by [ERC-3156](https://eips.ethereum.org/EIPS/eip-3156). 9 | interface IERC3156FlashLender { 10 | /// @notice The amount of currency available to be lent out. 11 | /// 12 | /// @param token The loan currency. 13 | /// 14 | /// @return amount The amount of `token` that can be borrowed. 15 | function maxFlashLoan(address token) external view returns (uint256 amount); 16 | 17 | /// @notice The fee to be charged for a given loan. 18 | /// 19 | /// @param token The loan currency. 20 | /// @param amount The amount of tokens lent. 21 | /// 22 | /// @return fee The amount of token to be charged for the loan, on top of the returned principal. 23 | function flashFee(address token, uint256 amount) external view returns (uint256 fee); 24 | 25 | /// @notice Initiate a flash loan. 26 | /// 27 | /// @param receiver The receiver of the tokens in the loan and the receiver of the callback. 28 | /// @param token The loan currency. 29 | /// @param amount The amount of tokens lent. 30 | /// @param data Arbitrary data structure, intended to contain user-defined parameters. 31 | /// 32 | /// @return success If the flash loan was successful. 33 | function flashLoan( 34 | IERC3156FlashBorrower receiver, 35 | address token, 36 | uint256 amount, 37 | bytes calldata data 38 | ) external returns (bool success); 39 | } -------------------------------------------------------------------------------- /contracts-full/test/TestYieldTokenAdapter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "../interfaces/ITokenAdapter.sol"; 4 | import "../interfaces/test/ITestYieldToken.sol"; 5 | 6 | import "../libraries/TokenUtils.sol"; 7 | 8 | /// @title TestYieldTokenAdapter 9 | /// @author Alchemix Finance 10 | contract TestYieldTokenAdapter is ITokenAdapter { 11 | string public constant override version = "2.0.0"; 12 | 13 | /// @inheritdoc ITokenAdapter 14 | address public immutable override token; 15 | 16 | /// @inheritdoc ITokenAdapter 17 | address public immutable override underlyingToken; 18 | 19 | constructor(address _token) { 20 | token = _token; 21 | underlyingToken = ITestYieldToken(_token).underlyingToken(); 22 | IERC20Minimal(ITestYieldToken(_token).underlyingToken()).approve(_token, type(uint256).max); 23 | } 24 | 25 | /// @inheritdoc ITokenAdapter 26 | function price() external view override returns (uint256) { 27 | return ITestYieldToken(token).price(); 28 | } 29 | 30 | /// @inheritdoc ITokenAdapter 31 | function wrap(uint256 amount, address recipient) external override returns (uint256) { 32 | TokenUtils.safeTransferFrom(underlyingToken, msg.sender, address(this), amount); 33 | return ITestYieldToken(token).mint(amount, recipient); 34 | } 35 | 36 | /// @inheritdoc ITokenAdapter 37 | function unwrap(uint256 amount, address recipient) external override returns (uint256) { 38 | TokenUtils.safeTransferFrom(token, msg.sender, address(this), amount); 39 | return ITestYieldToken(token).redeem(amount, recipient); 40 | } 41 | } -------------------------------------------------------------------------------- /contracts-hardhat/test/TestYieldTokenAdapter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "../interfaces/ITokenAdapter.sol"; 4 | import "../interfaces/test/ITestYieldToken.sol"; 5 | 6 | import "../libraries/TokenUtils.sol"; 7 | 8 | /// @title TestYieldTokenAdapter 9 | /// @author Alchemix Finance 10 | contract TestYieldTokenAdapter is ITokenAdapter { 11 | string public constant override version = "2.0.0"; 12 | 13 | /// @inheritdoc ITokenAdapter 14 | address public immutable override token; 15 | 16 | /// @inheritdoc ITokenAdapter 17 | address public immutable override underlyingToken; 18 | 19 | constructor(address _token) { 20 | token = _token; 21 | underlyingToken = ITestYieldToken(_token).underlyingToken(); 22 | IERC20Minimal(ITestYieldToken(_token).underlyingToken()).approve(_token, type(uint256).max); 23 | } 24 | 25 | /// @inheritdoc ITokenAdapter 26 | function price() external view override returns (uint256) { 27 | return ITestYieldToken(token).price(); 28 | } 29 | 30 | /// @inheritdoc ITokenAdapter 31 | function wrap(uint256 amount, address recipient) external override returns (uint256) { 32 | TokenUtils.safeTransferFrom(underlyingToken, msg.sender, address(this), amount); 33 | return ITestYieldToken(token).mint(amount, recipient); 34 | } 35 | 36 | /// @inheritdoc ITokenAdapter 37 | function unwrap(uint256 amount, address recipient) external override returns (uint256) { 38 | TokenUtils.safeTransferFrom(token, msg.sender, address(this), amount); 39 | return ITestYieldToken(token).redeem(amount, recipient); 40 | } 41 | } -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f44b-8A059.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/interfaces/external/aave/DataTypes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | // @dev Refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties. 5 | struct ReserveData { 6 | // Stores the reserve configuration. 7 | ReserveConfigurationMap configuration; 8 | // The liquidity index. Expressed in ray. 9 | uint128 liquidityIndex; 10 | // Variable borrow index. Expressed in ray. 11 | uint128 variableBorrowIndex; 12 | // The current supply rate. Expressed in ray. 13 | uint128 currentLiquidityRate; 14 | // The current variable borrow rate. Expressed in ray. 15 | uint128 currentVariableBorrowRate; 16 | // The current stable borrow rate. Expressed in ray. 17 | uint128 currentStableBorrowRate; 18 | uint40 lastUpdateTimestamp; 19 | // Tokens addresses. 20 | address aTokenAddress; 21 | address stableDebtTokenAddress; 22 | address variableDebtTokenAddress; 23 | // Address of the interest rate strategy. 24 | address interestRateStrategyAddress; 25 | // The id of the reserve. Represents the position in the list of the active reserves. 26 | uint8 id; 27 | } 28 | 29 | struct ReserveConfigurationMap { 30 | //bit 0-15: LTV 31 | //bit 16-31: Liq. threshold 32 | //bit 32-47: Liq. bonus 33 | //bit 48-55: Decimals 34 | //bit 56: Reserve is active 35 | //bit 57: reserve is frozen 36 | //bit 58: borrowing is enabled 37 | //bit 59: stable rate borrowing enabled 38 | //bit 60-63: reserved 39 | //bit 64-79: reserve factor 40 | uint256 data; 41 | } 42 | 43 | struct UserConfigurationMap { 44 | uint256 data; 45 | } 46 | 47 | enum InterestRateMode { 48 | NONE, 49 | STABLE, 50 | VARIABLE 51 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/external/aave/DataTypes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | // @dev Refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties. 5 | struct ReserveData { 6 | // Stores the reserve configuration. 7 | ReserveConfigurationMap configuration; 8 | // The liquidity index. Expressed in ray. 9 | uint128 liquidityIndex; 10 | // Variable borrow index. Expressed in ray. 11 | uint128 variableBorrowIndex; 12 | // The current supply rate. Expressed in ray. 13 | uint128 currentLiquidityRate; 14 | // The current variable borrow rate. Expressed in ray. 15 | uint128 currentVariableBorrowRate; 16 | // The current stable borrow rate. Expressed in ray. 17 | uint128 currentStableBorrowRate; 18 | uint40 lastUpdateTimestamp; 19 | // Tokens addresses. 20 | address aTokenAddress; 21 | address stableDebtTokenAddress; 22 | address variableDebtTokenAddress; 23 | // Address of the interest rate strategy. 24 | address interestRateStrategyAddress; 25 | // The id of the reserve. Represents the position in the list of the active reserves. 26 | uint8 id; 27 | } 28 | 29 | struct ReserveConfigurationMap { 30 | //bit 0-15: LTV 31 | //bit 16-31: Liq. threshold 32 | //bit 32-47: Liq. bonus 33 | //bit 48-55: Decimals 34 | //bit 56: Reserve is active 35 | //bit 57: reserve is frozen 36 | //bit 58: borrowing is enabled 37 | //bit 59: stable rate borrowing enabled 38 | //bit 60-63: reserved 39 | //bit 64-79: reserve factor 40 | uint256 data; 41 | } 42 | 43 | struct UserConfigurationMap { 44 | uint256 data; 45 | } 46 | 47 | enum InterestRateMode { 48 | NONE, 49 | STABLE, 50 | VARIABLE 51 | } -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f923-5854E.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f44d-27259.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f602-168C5.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/libraries/pools/Stake.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity ^0.8.11; 3 | 4 | import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 5 | 6 | import {FixedPointMath} from "../FixedPointMath.sol"; 7 | import {Pool} from "./Pool.sol"; 8 | 9 | /// @title Stake 10 | /// 11 | /// @dev A library which provides the Stake data struct and associated functions. 12 | library Stake { 13 | using FixedPointMath for FixedPointMath.Number; 14 | using Pool for Pool.Data; 15 | using Stake for Stake.Data; 16 | 17 | struct Data { 18 | uint256 totalDeposited; 19 | uint256 totalUnclaimed; 20 | FixedPointMath.Number lastAccumulatedWeight; 21 | } 22 | 23 | function update(Data storage _self, Pool.Data storage _pool, Pool.Context storage _ctx) internal { 24 | _self.totalUnclaimed = _self.getUpdatedTotalUnclaimed(_pool, _ctx); 25 | _self.lastAccumulatedWeight = _pool.getUpdatedAccumulatedRewardWeight(_ctx); 26 | } 27 | 28 | function getUpdatedTotalUnclaimed(Data storage _self, Pool.Data storage _pool, Pool.Context storage _ctx) 29 | internal view 30 | returns (uint256) 31 | { 32 | FixedPointMath.Number memory _currentAccumulatedWeight = _pool.getUpdatedAccumulatedRewardWeight(_ctx); 33 | FixedPointMath.Number memory _lastAccumulatedWeight = _self.lastAccumulatedWeight; 34 | 35 | if (_currentAccumulatedWeight.cmp(_lastAccumulatedWeight) == 0) { 36 | return _self.totalUnclaimed; 37 | } 38 | 39 | uint256 _distributedAmount = _currentAccumulatedWeight 40 | .sub(_lastAccumulatedWeight) 41 | .mul(_self.totalDeposited) 42 | .truncate(); 43 | 44 | return _self.totalUnclaimed + _distributedAmount; 45 | } 46 | } -------------------------------------------------------------------------------- /contracts-hardhat/libraries/pools/Stake.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0 2 | pragma solidity ^0.8.11; 3 | 4 | import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 5 | 6 | import {FixedPointMath} from "../FixedPointMath.sol"; 7 | import {Pool} from "./Pool.sol"; 8 | 9 | /// @title Stake 10 | /// 11 | /// @dev A library which provides the Stake data struct and associated functions. 12 | library Stake { 13 | using FixedPointMath for FixedPointMath.Number; 14 | using Pool for Pool.Data; 15 | using Stake for Stake.Data; 16 | 17 | struct Data { 18 | uint256 totalDeposited; 19 | uint256 totalUnclaimed; 20 | FixedPointMath.Number lastAccumulatedWeight; 21 | } 22 | 23 | function update(Data storage _self, Pool.Data storage _pool, Pool.Context storage _ctx) internal { 24 | _self.totalUnclaimed = _self.getUpdatedTotalUnclaimed(_pool, _ctx); 25 | _self.lastAccumulatedWeight = _pool.getUpdatedAccumulatedRewardWeight(_ctx); 26 | } 27 | 28 | function getUpdatedTotalUnclaimed(Data storage _self, Pool.Data storage _pool, Pool.Context storage _ctx) 29 | internal view 30 | returns (uint256) 31 | { 32 | FixedPointMath.Number memory _currentAccumulatedWeight = _pool.getUpdatedAccumulatedRewardWeight(_ctx); 33 | FixedPointMath.Number memory _lastAccumulatedWeight = _self.lastAccumulatedWeight; 34 | 35 | if (_currentAccumulatedWeight.cmp(_lastAccumulatedWeight) == 0) { 36 | return _self.totalUnclaimed; 37 | } 38 | 39 | uint256 _distributedAmount = _currentAccumulatedWeight 40 | .sub(_lastAccumulatedWeight) 41 | .mul(_self.totalDeposited) 42 | .truncate(); 43 | 44 | return _self.totalUnclaimed + _distributedAmount; 45 | } 46 | } -------------------------------------------------------------------------------- /contracts-full/utils/Whitelist.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "../base/Errors.sol"; 4 | import "../interfaces/IWhitelist.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | import "../libraries/Sets.sol"; 7 | 8 | /// @title Whitelist 9 | /// @author Alchemix Finance 10 | contract Whitelist is IWhitelist, Ownable { 11 | using Sets for Sets.AddressSet; 12 | Sets.AddressSet addresses; 13 | 14 | /// @inheritdoc IWhitelist 15 | bool public override disabled; 16 | 17 | constructor() Ownable() {} 18 | 19 | /// @inheritdoc IWhitelist 20 | function getAddresses() external view returns (address[] memory) { 21 | return addresses.values; 22 | } 23 | 24 | /// @inheritdoc IWhitelist 25 | function add(address caller) external override { 26 | _onlyAdmin(); 27 | if (disabled) { 28 | revert IllegalState(); 29 | } 30 | addresses.add(caller); 31 | emit AccountAdded(caller); 32 | } 33 | 34 | /// @inheritdoc IWhitelist 35 | function remove(address caller) external override { 36 | _onlyAdmin(); 37 | if (disabled) { 38 | revert IllegalState(); 39 | } 40 | addresses.remove(caller); 41 | emit AccountRemoved(caller); 42 | } 43 | 44 | /// @inheritdoc IWhitelist 45 | function disable() external override { 46 | _onlyAdmin(); 47 | disabled = true; 48 | emit WhitelistDisabled(); 49 | } 50 | 51 | /// @inheritdoc IWhitelist 52 | function isWhitelisted(address account) external view override returns (bool) { 53 | return disabled || addresses.contains(account); 54 | } 55 | 56 | /// @dev Reverts if the caller is not the contract owner. 57 | function _onlyAdmin() internal view { 58 | if (msg.sender != owner()) { 59 | revert Unauthorized(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /contracts-hardhat/utils/Whitelist.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "../base/Errors.sol"; 4 | import "../interfaces/IWhitelist.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | import "../libraries/Sets.sol"; 7 | 8 | /// @title Whitelist 9 | /// @author Alchemix Finance 10 | contract Whitelist is IWhitelist, Ownable { 11 | using Sets for Sets.AddressSet; 12 | Sets.AddressSet addresses; 13 | 14 | /// @inheritdoc IWhitelist 15 | bool public override disabled; 16 | 17 | constructor() Ownable() {} 18 | 19 | /// @inheritdoc IWhitelist 20 | function getAddresses() external view returns (address[] memory) { 21 | return addresses.values; 22 | } 23 | 24 | /// @inheritdoc IWhitelist 25 | function add(address caller) external override { 26 | _onlyAdmin(); 27 | if (disabled) { 28 | revert IllegalState(); 29 | } 30 | addresses.add(caller); 31 | emit AccountAdded(caller); 32 | } 33 | 34 | /// @inheritdoc IWhitelist 35 | function remove(address caller) external override { 36 | _onlyAdmin(); 37 | if (disabled) { 38 | revert IllegalState(); 39 | } 40 | addresses.remove(caller); 41 | emit AccountRemoved(caller); 42 | } 43 | 44 | /// @inheritdoc IWhitelist 45 | function disable() external override { 46 | _onlyAdmin(); 47 | disabled = true; 48 | emit WhitelistDisabled(); 49 | } 50 | 51 | /// @inheritdoc IWhitelist 52 | function isWhitelisted(address account) external view override returns (bool) { 53 | return disabled || addresses.contains(account); 54 | } 55 | 56 | /// @dev Reverts if the caller is not the contract owner. 57 | function _onlyAdmin() internal view { 58 | if (msg.sender != owner()) { 59 | revert Unauthorized(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /contracts-full/libraries/LiquidityMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import { IllegalArgument } from "../base/Errors.sol"; 5 | 6 | import { FixedPointMath } from "./FixedPointMath.sol"; 7 | 8 | /// @title LiquidityMath 9 | /// @author Alchemix Finance 10 | library LiquidityMath { 11 | using FixedPointMath for FixedPointMath.Number; 12 | 13 | /// @dev Adds a signed delta to an unsigned integer. 14 | /// 15 | /// @param x The unsigned value to add the delta to. 16 | /// @param y The signed delta value to add. 17 | /// @return z The result. 18 | function addDelta(uint256 x, int256 y) internal pure returns (uint256 z) { 19 | if (y < 0) { 20 | if ((z = x - uint256(-y)) >= x) { 21 | revert IllegalArgument(); 22 | } 23 | } else { 24 | if ((z = x + uint256(y)) < x) { 25 | revert IllegalArgument(); 26 | } 27 | } 28 | } 29 | 30 | /// @dev Calculate a uint256 representation of x * y using FixedPointMath 31 | /// 32 | /// @param x The first factor 33 | /// @param y The second factor (fixed point) 34 | /// @return z The resulting product, after truncation 35 | function calculateProduct(uint256 x, FixedPointMath.Number memory y) internal pure returns (uint256 z) { 36 | z = y.mul(x).truncate(); 37 | } 38 | 39 | /// @notice normalises non 18 digit token values to 18 digits. 40 | function normalizeValue(uint256 input, uint256 decimals) internal pure returns (uint256) { 41 | return (input * (10**18)) / (10**decimals); 42 | } 43 | 44 | /// @notice denormalizes 18 digits back to a token's digits 45 | function deNormalizeValue(uint256 input, uint256 decimals) internal pure returns (uint256) { 46 | return (input * (10**decimals)) / (10**18); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /contracts-hardhat/libraries/LiquidityMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import { IllegalArgument } from "../base/Errors.sol"; 5 | 6 | import { FixedPointMath } from "./FixedPointMath.sol"; 7 | 8 | /// @title LiquidityMath 9 | /// @author Alchemix Finance 10 | library LiquidityMath { 11 | using FixedPointMath for FixedPointMath.Number; 12 | 13 | /// @dev Adds a signed delta to an unsigned integer. 14 | /// 15 | /// @param x The unsigned value to add the delta to. 16 | /// @param y The signed delta value to add. 17 | /// @return z The result. 18 | function addDelta(uint256 x, int256 y) internal pure returns (uint256 z) { 19 | if (y < 0) { 20 | if ((z = x - uint256(-y)) >= x) { 21 | revert IllegalArgument(); 22 | } 23 | } else { 24 | if ((z = x + uint256(y)) < x) { 25 | revert IllegalArgument(); 26 | } 27 | } 28 | } 29 | 30 | /// @dev Calculate a uint256 representation of x * y using FixedPointMath 31 | /// 32 | /// @param x The first factor 33 | /// @param y The second factor (fixed point) 34 | /// @return z The resulting product, after truncation 35 | function calculateProduct(uint256 x, FixedPointMath.Number memory y) internal pure returns (uint256 z) { 36 | z = y.mul(x).truncate(); 37 | } 38 | 39 | /// @notice normalises non 18 digit token values to 18 digits. 40 | function normalizeValue(uint256 input, uint256 decimals) internal pure returns (uint256) { 41 | return (input * (10**18)) / (10**decimals); 42 | } 43 | 44 | /// @notice denormalizes 18 digits back to a token's digits 45 | function deNormalizeValue(uint256 input, uint256 decimals) internal pure returns (uint256) { 46 | return (input * (10**decimals)) / (10**18); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /contracts-full/interfaces/compound/ICERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.13; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | import {IInterestRateModel} from "./IInterestRateModel.sol"; 7 | 8 | interface ICERC20 is IERC20 { 9 | function mint(uint256) external returns (uint256); 10 | 11 | function borrow(uint256) external returns (uint256); 12 | 13 | function underlying() external view returns (address); 14 | 15 | function totalBorrows() external view returns (uint256); 16 | 17 | function totalFuseFees() external view returns (uint256); 18 | 19 | function repayBorrow(uint256) external returns (uint256); 20 | 21 | function totalReserves() external view returns (uint256); 22 | 23 | function exchangeRateCurrent() external returns (uint256); 24 | 25 | function totalAdminFees() external view returns (uint256); 26 | 27 | function fuseFeeMantissa() external view returns (uint256); 28 | 29 | function adminFeeMantissa() external view returns (uint256); 30 | 31 | function exchangeRateStored() external view returns (uint256); 32 | 33 | function accrualBlockNumber() external view returns (uint256); 34 | 35 | function redeemUnderlying(uint256) external returns (uint256); 36 | 37 | function redeem(uint redeemTokens) external returns (uint); 38 | 39 | function balanceOfUnderlying(address) external returns (uint256); 40 | 41 | function reserveFactorMantissa() external view returns (uint256); 42 | 43 | function borrowBalanceCurrent(address) external returns (uint256); 44 | 45 | function interestRateModel() external view returns (IInterestRateModel); 46 | 47 | function initialExchangeRateMantissa() external view returns (uint256); 48 | 49 | function repayBorrowBehalf(address, uint256) external returns (uint256); 50 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/ITokenAdapter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | /// @title ITokenAdapter 4 | /// @author Alchemix Finance 5 | interface ITokenAdapter { 6 | /// @notice Gets the current version. 7 | /// 8 | /// @return The version. 9 | function version() external view returns (string memory); 10 | 11 | /// @notice Gets the address of the yield token that this adapter supports. 12 | /// 13 | /// @return The address of the yield token. 14 | function token() external view returns (address); 15 | 16 | /// @notice Gets the address of the underlying token that the yield token wraps. 17 | /// 18 | /// @return The address of the underlying token. 19 | function underlyingToken() external view returns (address); 20 | 21 | /// @notice Gets the number of underlying tokens that a single whole yield token is redeemable 22 | /// for. 23 | /// 24 | /// @return The price. 25 | function price() external view returns (uint256); 26 | 27 | /// @notice Wraps `amount` underlying tokens into the yield token. 28 | /// 29 | /// @param amount The amount of the underlying token to wrap. 30 | /// @param recipient The address which will receive the yield tokens. 31 | /// 32 | /// @return amountYieldTokens The amount of yield tokens minted to `recipient`. 33 | function wrap(uint256 amount, address recipient) 34 | external 35 | returns (uint256 amountYieldTokens); 36 | 37 | /// @notice Unwraps `amount` yield tokens into the underlying token. 38 | /// 39 | /// @param amount The amount of yield-tokens to redeem. 40 | /// @param recipient The recipient of the resulting underlying-tokens. 41 | /// 42 | /// @return amountUnderlyingTokens The amount of underlying tokens unwrapped to `recipient`. 43 | function unwrap(uint256 amount, address recipient) 44 | external 45 | returns (uint256 amountUnderlyingTokens); 46 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IStakingPools.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.11; 3 | 4 | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import {IERC20Mintable} from "./IERC20Mintable.sol"; 6 | 7 | interface IStakingPools { 8 | function acceptGovernance() external; 9 | function claim(uint256 _poolId) external; 10 | function claimExact(uint256 _poolId, uint256 _claimAmount) external; 11 | function createPool(IERC20 _token) external returns (uint256); 12 | function deposit(uint256 _poolId, uint256 _depositAmount) external; 13 | function exit(uint256 _poolId) external; 14 | function getPoolRewardRate(uint256 _poolId) view external returns (uint256); 15 | function getPoolRewardWeight(uint256 _poolId) view external returns (uint256); 16 | function getPoolToken(uint256 _poolId) view external returns (address); 17 | function getPoolTotalDeposited(uint256 _poolId) view external returns (uint256); 18 | function getStakeTotalDeposited(address _account, uint256 _poolId) view external returns (uint256); 19 | function getStakeTotalUnclaimed(address _account, uint256 _poolId) view external returns (uint256); 20 | function governance() view external returns (address); 21 | function pendingGovernance() view external returns (address); 22 | function poolCount() view external returns (uint256); 23 | function reward() view external returns (IERC20Mintable); 24 | function rewardRate() view external returns (uint256); 25 | function setPendingGovernance(address _pendingGovernance) external; 26 | function setRewardRate(uint256 _rewardRate) external; 27 | function setRewardWeights(uint256[] memory _rewardWeights) external; 28 | function tokenPoolIds(IERC20 _token) view external returns (uint256); 29 | function totalRewardWeight() view external returns (uint256); 30 | function withdraw(uint256 _poolId, uint256 _withdrawAmount) external; 31 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/test/ITestYieldToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | /// @title ITestYieldToken 6 | /// @author Alchemix Finance 7 | interface ITestYieldToken is IERC20 { 8 | /// @notice Gets the address of underlying token that the yield token wraps. 9 | /// 10 | /// @return The underlying token address. 11 | function underlyingToken() external view returns (address); 12 | 13 | /// @notice Gets the conversion rate of one whole unit of this token for the underlying token. 14 | /// 15 | /// @return The price. 16 | function price() external view returns (uint256); 17 | 18 | /// @notice Mints an amount of yield tokens from `amount` underlying tokens and transfers them to `recipient`. 19 | /// 20 | /// @param amount The amount of underlying tokens. 21 | /// @param recipient The address which will receive the minted yield tokens. 22 | /// 23 | /// @return The amount of minted yield tokens. 24 | function mint(uint256 amount, address recipient) external returns (uint256); 25 | 26 | /// @notice Redeems yield tokens for underlying tokens. 27 | /// 28 | /// @param amount The amount of yield tokens to redeem. 29 | /// @param recipient The address which will receive the redeemed underlying tokens. 30 | /// 31 | /// @return The amount of underlying tokens that the yield tokens were redeemed for. 32 | function redeem(uint256 amount, address recipient) external returns (uint256); 33 | 34 | /// @notice Simulates an atomic harvest of `amount` underlying tokens. 35 | /// 36 | /// @param amount The amount of the underlying token. 37 | function slurp(uint256 amount) external; 38 | 39 | /// @notice Simulates an atomic loss of `amount` underlying tokens. 40 | /// 41 | /// @param amount The amount of the underlying token. 42 | function siphon(uint256 amount) external; 43 | } 44 | -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IStakingPools.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.11; 3 | 4 | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import {IERC20Mintable} from "./IERC20Mintable.sol"; 6 | 7 | interface IStakingPools { 8 | function acceptGovernance() external; 9 | function claim(uint256 _poolId) external; 10 | function claimExact(uint256 _poolId, uint256 _claimAmount) external; 11 | function createPool(IERC20 _token) external returns (uint256); 12 | function deposit(uint256 _poolId, uint256 _depositAmount) external; 13 | function exit(uint256 _poolId) external; 14 | function getPoolRewardRate(uint256 _poolId) view external returns (uint256); 15 | function getPoolRewardWeight(uint256 _poolId) view external returns (uint256); 16 | function getPoolToken(uint256 _poolId) view external returns (address); 17 | function getPoolTotalDeposited(uint256 _poolId) view external returns (uint256); 18 | function getStakeTotalDeposited(address _account, uint256 _poolId) view external returns (uint256); 19 | function getStakeTotalUnclaimed(address _account, uint256 _poolId) view external returns (uint256); 20 | function governance() view external returns (address); 21 | function pendingGovernance() view external returns (address); 22 | function poolCount() view external returns (uint256); 23 | function reward() view external returns (IERC20Mintable); 24 | function rewardRate() view external returns (uint256); 25 | function setPendingGovernance(address _pendingGovernance) external; 26 | function setRewardRate(uint256 _rewardRate) external; 27 | function setRewardWeights(uint256[] memory _rewardWeights) external; 28 | function tokenPoolIds(IERC20 _token) view external returns (uint256); 29 | function totalRewardWeight() view external returns (uint256); 30 | function withdraw(uint256 _poolId, uint256 _withdrawAmount) external; 31 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/test/ITestYieldToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | 5 | /// @title ITestYieldToken 6 | /// @author Alchemix Finance 7 | interface ITestYieldToken is IERC20 { 8 | /// @notice Gets the address of underlying token that the yield token wraps. 9 | /// 10 | /// @return The underlying token address. 11 | function underlyingToken() external view returns (address); 12 | 13 | /// @notice Gets the conversion rate of one whole unit of this token for the underlying token. 14 | /// 15 | /// @return The price. 16 | function price() external view returns (uint256); 17 | 18 | /// @notice Mints an amount of yield tokens from `amount` underlying tokens and transfers them to `recipient`. 19 | /// 20 | /// @param amount The amount of underlying tokens. 21 | /// @param recipient The address which will receive the minted yield tokens. 22 | /// 23 | /// @return The amount of minted yield tokens. 24 | function mint(uint256 amount, address recipient) external returns (uint256); 25 | 26 | /// @notice Redeems yield tokens for underlying tokens. 27 | /// 28 | /// @param amount The amount of yield tokens to redeem. 29 | /// @param recipient The address which will receive the redeemed underlying tokens. 30 | /// 31 | /// @return The amount of underlying tokens that the yield tokens were redeemed for. 32 | function redeem(uint256 amount, address recipient) external returns (uint256); 33 | 34 | /// @notice Simulates an atomic harvest of `amount` underlying tokens. 35 | /// 36 | /// @param amount The amount of the underlying token. 37 | function slurp(uint256 amount) external; 38 | 39 | /// @notice Simulates an atomic loss of `amount` underlying tokens. 40 | /// 41 | /// @param amount The amount of the underlying token. 42 | function siphon(uint256 amount) external; 43 | } 44 | -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/ITokenAdapter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | /// @title ITokenAdapter 4 | /// @author Alchemix Finance 5 | interface ITokenAdapter { 6 | /// @notice Gets the current version. 7 | /// 8 | /// @return The version. 9 | function version() external view returns (string memory); 10 | 11 | /// @notice Gets the address of the yield token that this adapter supports. 12 | /// 13 | /// @return The address of the yield token. 14 | function token() external view returns (address); 15 | 16 | /// @notice Gets the address of the underlying token that the yield token wraps. 17 | /// 18 | /// @return The address of the underlying token. 19 | function underlyingToken() external view returns (address); 20 | 21 | /// @notice Gets the number of underlying tokens that a single whole yield token is redeemable for. 22 | /// 23 | /// @return The price. 24 | function price() external view returns (uint256); 25 | 26 | /// @notice Wraps `amount` underlying tokens into the yield token. 27 | /// 28 | /// @param amount The amount of the underlying token to wrap. 29 | /// @param recipient The address which will receive the yield tokens. 30 | /// 31 | /// @return amountYieldTokens The amount of yield tokens minted to `recipient`. 32 | function wrap(uint256 amount, address recipient) 33 | external 34 | returns (uint256 amountYieldTokens); 35 | 36 | /// @notice Unwraps `amount` yield tokens into the underlying token. 37 | /// 38 | /// @param amount The amount of yield-tokens to redeem. 39 | /// @param recipient The recipient of the resulting underlying-tokens. 40 | /// 41 | /// @return amountUnderlyingTokens The amount of underlying tokens unwrapped to `recipient`. 42 | function unwrap(uint256 amount, address recipient) 43 | external 44 | returns (uint256 amountUnderlyingTokens); 45 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/vesper/IVesperPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity >=0.5.0; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | interface IVesperPool is IERC20 { 7 | function deposit() external payable; 8 | 9 | function deposit(uint256 _share) external; 10 | 11 | function governor() external returns (address); 12 | 13 | function keepers() external returns (address); 14 | 15 | function multiTransfer(address[] memory _recipients, uint256[] memory _amounts) 16 | external 17 | returns (bool); 18 | 19 | function excessDebt(address _strategy) external view returns (uint256); 20 | 21 | function permit( 22 | address, 23 | address, 24 | uint256, 25 | uint256, 26 | uint8, 27 | bytes32, 28 | bytes32 29 | ) external; 30 | 31 | function reportEarning( 32 | uint256 _profit, 33 | uint256 _loss, 34 | uint256 _payback 35 | ) external; 36 | 37 | function resetApproval() external; 38 | 39 | function sweepERC20(address _fromToken) external; 40 | 41 | function withdraw(uint256 _amount) external; 42 | 43 | function withdrawETH(uint256 _amount) external; 44 | 45 | function whitelistedWithdraw(uint256 _amount) external; 46 | 47 | function feeCollector() external view returns (address); 48 | 49 | function pricePerShare() external view returns (uint256); 50 | 51 | function token() external view returns (address); 52 | 53 | function tokensHere() external view returns (uint256); 54 | 55 | function totalDebtOf(address _strategy) external view returns (uint256); 56 | 57 | function totalValue() external view returns (uint256); 58 | 59 | function withdrawFee() external view returns (uint256); 60 | 61 | function poolRewards() external view returns (address); 62 | 63 | function getStrategies() external view returns (address[] memory); 64 | } -------------------------------------------------------------------------------- /test-hardhat/Sets.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import { Wallet } from "ethers"; 3 | import { ethers, waffle } from "hardhat"; 4 | import { TestSets } from "../typechain"; 5 | 6 | describe("Sets", () => { 7 | let wallet: Wallet; 8 | let other: Wallet; 9 | let testSets: TestSets; 10 | 11 | before(async () => { 12 | [wallet, other] = waffle.provider.getWallets(); 13 | }); 14 | 15 | beforeEach(async () => { 16 | const testSetsFactory = await ethers.getContractFactory("TestSets"); 17 | testSets = (await testSetsFactory.connect(wallet).deploy()) as TestSets; 18 | }); 19 | 20 | describe("add", () => { 21 | it("adds an item to the set", async () => { 22 | await testSets.add(wallet.address); 23 | await testSets.add(other.address); 24 | const checkWallet = await testSets.contains(wallet.address); 25 | expect(checkWallet).equals(true); 26 | const checkOther = await testSets.contains(wallet.address); 27 | expect(checkOther).equals(true); 28 | }); 29 | 30 | it("cannot add an item to the set if it already exists in the set", async () => { 31 | await testSets.add(wallet.address); 32 | await expect(testSets.add(wallet.address)).revertedWith("failed to add"); 33 | }); 34 | }); 35 | 36 | describe("remove", () => { 37 | it("removes an item from the set", async () => { 38 | await testSets.add(wallet.address); 39 | await testSets.add(other.address); 40 | await testSets.remove(wallet.address); 41 | const checkWallet = await testSets.contains(wallet.address); 42 | expect(checkWallet).equals(false); 43 | const checkOther = await testSets.contains(other.address); 44 | expect(checkOther).equals(true); 45 | }); 46 | 47 | it("cannot remove an item from the set if it does not already exist in the set", async () => { 48 | await expect(testSets.remove(wallet.address)).revertedWith( 49 | "failed to remove" 50 | ); 51 | }); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /test-forge/TransmuterConduit.t.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.13; 2 | 3 | import "ds-test/test.sol"; 4 | import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; 5 | import "./utils/DSTestPlus.sol"; 6 | import "../TransmuterConduit.sol"; 7 | import "./utils/mocks/ERC20Mock.sol"; 8 | import "./mocks/TransmuterBufferMock.sol"; 9 | import "./utils/Hevm.sol"; 10 | import "forge-std/console.sol"; 11 | 12 | contract TransmuterConduitTest is DSTestPlus { 13 | ERC20Mock token; 14 | TransmuterConduit transmuterConduit; 15 | TransmuterBufferMock transmuterBuffer; 16 | 17 | address transmuterSource = 0x000000000000000000000000000000000000dEaD; 18 | 19 | function setUp() public { 20 | token = new ERC20Mock("TestToken", "TEST", 18); 21 | transmuterBuffer = new TransmuterBufferMock(address(token)); 22 | transmuterConduit = new TransmuterConduit(address(token), transmuterSource, address(transmuterBuffer)); 23 | token.mint(transmuterSource, 100*10e18); 24 | } 25 | 26 | function testDistribute() public { 27 | uint256 amount = 10*10e18; 28 | hevm.startPrank(transmuterSource); 29 | token.approve(address(transmuterConduit), amount); 30 | transmuterConduit.distribute(transmuterSource, amount); 31 | uint256 endingBal = token.balanceOf(address(transmuterBuffer)); 32 | console.log(endingBal); 33 | assertEq(endingBal, amount); 34 | } 35 | 36 | function testFailDistributeNoApproval() public { 37 | uint256 amount = 10*10e18; 38 | hevm.startPrank(transmuterSource); 39 | transmuterConduit.distribute(transmuterSource, amount); 40 | } 41 | 42 | function testFailDistrubteUnauthorized() public { 43 | address badSource = 0x0000000000000000000000000000000000000Bad; 44 | uint256 amount = 10*10e18; 45 | hevm.startPrank(badSource); 46 | token.approve(address(transmuterConduit), amount); 47 | transmuterConduit.distribute(transmuterSource, amount); 48 | } 49 | } -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f4c6-44E30.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/interfaces/IWhitelist.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | /// @title Whitelist 4 | /// @author Alchemix Finance 5 | interface IWhitelist { 6 | /// @dev Emitted when a contract is added to the whitelist. 7 | /// 8 | /// @param account The account that was added to the whitelist. 9 | event AccountAdded(address account); 10 | 11 | /// @dev Emitted when a contract is removed from the whitelist. 12 | /// 13 | /// @param account The account that was removed from the whitelist. 14 | event AccountRemoved(address account); 15 | 16 | /// @dev Emitted when the whitelist is deactivated. 17 | event WhitelistDisabled(); 18 | 19 | /// @dev Returns the list of addresses that are whitelisted for the given contract address. 20 | /// 21 | /// @return addresses The addresses that are whitelisted to interact with the given contract. 22 | function getAddresses() external view returns (address[] memory addresses); 23 | 24 | /// @dev Returns the disabled status of a given whitelist. 25 | /// 26 | /// @return disabled A flag denoting if the given whitelist is disabled. 27 | function disabled() external view returns (bool); 28 | 29 | /// @dev Adds an contract to the whitelist. 30 | /// 31 | /// @param caller The address to add to the whitelist. 32 | function add(address caller) external; 33 | 34 | /// @dev Adds a contract to the whitelist. 35 | /// 36 | /// @param caller The address to remove from the whitelist. 37 | function remove(address caller) external; 38 | 39 | /// @dev Disables the whitelist of the target whitelisted contract. 40 | /// 41 | /// This can only occur once. Once the whitelist is disabled, then it cannot be reenabled. 42 | function disable() external; 43 | 44 | /// @dev Checks that the `msg.sender` is whitelisted when it is not an EOA. 45 | /// 46 | /// @param account The account to check. 47 | /// 48 | /// @return whitelisted A flag denoting if the given account is whitelisted. 49 | function isWhitelisted(address account) external view returns (bool); 50 | } 51 | -------------------------------------------------------------------------------- /contracts-full/AutoleverageCurveFactoryethpool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.11; 3 | 4 | import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; 5 | 6 | import {ICurveFactoryethpool} from "./interfaces/ICurveFactoryethpool.sol"; 7 | import {IWETH9} from "./interfaces/external/IWETH9.sol"; 8 | 9 | import {AutoleverageBase} from "./AutoleverageBase.sol"; 10 | 11 | /// @title A zapper for leveraged deposits into the Alchemist 12 | contract AutoleverageCurveFactoryethpool is AutoleverageBase { 13 | 14 | address public constant wethAddress = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; 15 | 16 | /// @notice Used to receive ETH from factory pool swaps 17 | receive() external payable {} 18 | 19 | /// @inheritdoc AutoleverageBase 20 | function _transferTokensToSelf(address underlyingToken, uint256 collateralInitial) internal override { 21 | // Convert eth to weth if received eth, otherwise transfer weth 22 | if (msg.value > 0) { 23 | if (msg.value != collateralInitial) revert IllegalArgument("msg.value doesn't match collateralInitial"); 24 | IWETH9(wethAddress).deposit{value: msg.value}(); 25 | } else { 26 | IERC20(underlyingToken).transferFrom(msg.sender, address(this), collateralInitial); 27 | } 28 | } 29 | 30 | /// @inheritdoc AutoleverageBase 31 | function _maybeConvertCurveOutput(uint256 amountOut) internal override { 32 | // Convert ETH output from Curve into WETH 33 | IWETH9(wethAddress).deposit{value: amountOut}(); 34 | } 35 | 36 | /// @inheritdoc AutoleverageBase 37 | function _curveSwap(address poolAddress, address debtToken, int128 i, int128 j, uint256 minAmountOut) internal override returns (uint256 amountOut) { 38 | // Curve swap 39 | uint256 debtTokenBalance = IERC20(debtToken).balanceOf(address(this)); 40 | approve(debtToken, poolAddress); 41 | return ICurveFactoryethpool(poolAddress).exchange( 42 | i, 43 | j, 44 | debtTokenBalance, 45 | minAmountOut 46 | ); 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IWhitelist.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import "../base/Errors.sol"; 4 | import "@openzeppelin/contracts/access/Ownable.sol"; 5 | import "../libraries/Sets.sol"; 6 | 7 | /// @title Whitelist 8 | /// @author Alchemix Finance 9 | interface IWhitelist { 10 | /// @dev Emitted when a contract is added to the whitelist. 11 | /// 12 | /// @param account The account that was added to the whitelist. 13 | event AccountAdded(address account); 14 | 15 | /// @dev Emitted when a contract is removed from the whitelist. 16 | /// 17 | /// @param account The account that was removed from the whitelist. 18 | event AccountRemoved(address account); 19 | 20 | /// @dev Emitted when the whitelist is deactivated. 21 | event WhitelistDisabled(); 22 | 23 | /// @dev Returns the list of addresses that are whitelisted for the given contract address. 24 | /// 25 | /// @return addresses The addresses that are whitelisted to interact with the given contract. 26 | function getAddresses() external view returns (address[] memory addresses); 27 | 28 | /// @dev Returns the disabled status of a given whitelist. 29 | /// 30 | /// @return disabled A flag denoting if the given whitelist is disabled. 31 | function disabled() external view returns (bool); 32 | 33 | /// @dev Adds an contract to the whitelist. 34 | /// 35 | /// @param caller The address to add to the whitelist. 36 | function add(address caller) external; 37 | 38 | /// @dev Adds a contract to the whitelist. 39 | /// 40 | /// @param caller The address to remove from the whitelist. 41 | function remove(address caller) external; 42 | 43 | /// @dev Disables the whitelist of the target whitelisted contract. 44 | /// 45 | /// This can only occur once. Once the whitelist is disabled, then it cannot be reenabled. 46 | function disable() external; 47 | 48 | /// @dev Checks that the `msg.sender` is whitelisted when it is not an EOA. 49 | /// 50 | /// @param account The account to check. 51 | /// 52 | /// @return whitelisted A flag denoting if the given account is whitelisted. 53 | function isWhitelisted(address account) external view returns (bool); 54 | } 55 | -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f911-F346C.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/interfaces/rocket/IRocketStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | pragma solidity >=0.5.0; 3 | 4 | interface IRocketStorage { 5 | function getDeployedStatus() external view returns (bool); 6 | function getGuardian() external view returns(address); 7 | function setGuardian(address value) external; 8 | function confirmGuardian() external; 9 | 10 | function getAddress(bytes32 key) external view returns (address); 11 | function getUint(bytes32 key) external view returns (uint); 12 | function getString(bytes32 key) external view returns (string memory); 13 | function getBytes(bytes32 key) external view returns (bytes memory); 14 | function getBool(bytes32 key) external view returns (bool); 15 | function getInt(bytes32 key) external view returns (int); 16 | function getBytes32(bytes32 key) external view returns (bytes32); 17 | 18 | function setAddress(bytes32 key, address value) external; 19 | function setUint(bytes32 key, uint value) external; 20 | function setString(bytes32 key, string calldata value) external; 21 | function setBytes(bytes32 key, bytes calldata value) external; 22 | function setBool(bytes32 key, bool value) external; 23 | function setInt(bytes32 key, int value) external; 24 | function setBytes32(bytes32 key, bytes32 value) external; 25 | 26 | function deleteAddress(bytes32 key) external; 27 | function deleteUint(bytes32 key) external; 28 | function deleteString(bytes32 key) external; 29 | function deleteBytes(bytes32 key) external; 30 | function deleteBool(bytes32 key) external; 31 | function deleteInt(bytes32 key) external; 32 | function deleteBytes32(bytes32 key) external; 33 | 34 | function addUint(bytes32 key, uint256 amount) external; 35 | function subUint(bytes32 key, uint256 amount) external; 36 | 37 | function getNodeWithdrawalAddress(address nodeAddress) external view returns (address); 38 | function getNodePendingWithdrawalAddress(address nodeAddress) external view returns (address); 39 | function setWithdrawalAddress(address nodeAddress, address newWithdrawalAddress, bool confirm) external; 40 | function confirmWithdrawalAddress(address nodeAddress) external; 41 | } -------------------------------------------------------------------------------- /discord-export/Code4rena - ARCHIVE-Q2-2022 - ☑alchemix-may5 [971041376785539093].html_Files/1f43a-EB486.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts-full/base/SelfPermit.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol"; 6 | 7 | import "../interfaces/ISelfPermit.sol"; 8 | import "../interfaces/IERC20PermitAllowed.sol"; 9 | 10 | /// @title Self Permit 11 | /// @author Uniswap Labs 12 | /// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route 13 | /// 14 | /// @dev These functions are expected to be embedded in multicalls to allow EOAs to approve a contract and call a function 15 | /// that requires an approval in a single transaction. 16 | abstract contract SelfPermit is ISelfPermit { 17 | /// @inheritdoc ISelfPermit 18 | function selfPermit( 19 | address token, 20 | uint256 value, 21 | uint256 deadline, 22 | uint8 v, 23 | bytes32 r, 24 | bytes32 s 25 | ) public payable override { 26 | IERC20Permit(token).permit(msg.sender, address(this), value, deadline, v, r, s); 27 | } 28 | 29 | /// @inheritdoc ISelfPermit 30 | function selfPermitIfNecessary( 31 | address token, 32 | uint256 value, 33 | uint256 deadline, 34 | uint8 v, 35 | bytes32 r, 36 | bytes32 s 37 | ) external payable override { 38 | if (IERC20(token).allowance(msg.sender, address(this)) < value) selfPermit(token, value, deadline, v, r, s); 39 | } 40 | 41 | /// @inheritdoc ISelfPermit 42 | function selfPermitAllowed( 43 | address token, 44 | uint256 nonce, 45 | uint256 expiry, 46 | uint8 v, 47 | bytes32 r, 48 | bytes32 s 49 | ) public payable override { 50 | IERC20PermitAllowed(token).permit(msg.sender, address(this), nonce, expiry, true, v, r, s); 51 | } 52 | 53 | /// @inheritdoc ISelfPermit 54 | function selfPermitAllowedIfNecessary( 55 | address token, 56 | uint256 nonce, 57 | uint256 expiry, 58 | uint8 v, 59 | bytes32 r, 60 | bytes32 s 61 | ) external payable override { 62 | if (IERC20(token).allowance(msg.sender, address(this)) < type(uint256).max) 63 | selfPermitAllowed(token, nonce, expiry, v, r, s); 64 | } 65 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # Hardhat artifacts 107 | .openzeppelin/ 108 | artifacts/ 109 | cache/ 110 | typechain/ 111 | 112 | # Node artifacts 113 | yarn.lock 114 | 115 | -------------------------------------------------------------------------------- /contracts-hardhat/base/SelfPermit.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol"; 6 | 7 | import "../interfaces/ISelfPermit.sol"; 8 | import "../interfaces/IERC20PermitAllowed.sol"; 9 | 10 | /// @title Self Permit 11 | /// @author Uniswap Labs 12 | /// @notice Functionality to call permit on any EIP-2612-compliant token for use in the route 13 | /// 14 | /// @dev These functions are expected to be embedded in multicalls to allow EOAs to approve a contract and call a function 15 | /// that requires an approval in a single transaction. 16 | abstract contract SelfPermit is ISelfPermit { 17 | /// @inheritdoc ISelfPermit 18 | function selfPermit( 19 | address token, 20 | uint256 value, 21 | uint256 deadline, 22 | uint8 v, 23 | bytes32 r, 24 | bytes32 s 25 | ) public payable override { 26 | IERC20Permit(token).permit(msg.sender, address(this), value, deadline, v, r, s); 27 | } 28 | 29 | /// @inheritdoc ISelfPermit 30 | function selfPermitIfNecessary( 31 | address token, 32 | uint256 value, 33 | uint256 deadline, 34 | uint8 v, 35 | bytes32 r, 36 | bytes32 s 37 | ) external payable override { 38 | if (IERC20(token).allowance(msg.sender, address(this)) < value) selfPermit(token, value, deadline, v, r, s); 39 | } 40 | 41 | /// @inheritdoc ISelfPermit 42 | function selfPermitAllowed( 43 | address token, 44 | uint256 nonce, 45 | uint256 expiry, 46 | uint8 v, 47 | bytes32 r, 48 | bytes32 s 49 | ) public payable override { 50 | IERC20PermitAllowed(token).permit(msg.sender, address(this), nonce, expiry, true, v, r, s); 51 | } 52 | 53 | /// @inheritdoc ISelfPermit 54 | function selfPermitAllowedIfNecessary( 55 | address token, 56 | uint256 nonce, 57 | uint256 expiry, 58 | uint8 v, 59 | bytes32 r, 60 | bytes32 s 61 | ) external payable override { 62 | if (IERC20(token).allowance(msg.sender, address(this)) < type(uint256).max) 63 | selfPermitAllowed(token, nonce, expiry, v, r, s); 64 | } 65 | } -------------------------------------------------------------------------------- /contracts-full/libraries/Sets.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | /// @title Sets 4 | /// @author Alchemix Finance 5 | library Sets { 6 | using Sets for AddressSet; 7 | 8 | /// @notice A data structure holding an array of values with an index mapping for O(1) lookup. 9 | struct AddressSet { 10 | address[] values; 11 | mapping(address => uint256) indexes; 12 | } 13 | 14 | /// @dev Add a value to a Set 15 | /// 16 | /// @param self The Set. 17 | /// @param value The value to add. 18 | /// 19 | /// @return Whether the operation was successful (unsuccessful if the value is already contained in the Set) 20 | function add(AddressSet storage self, address value) internal returns (bool) { 21 | if (self.contains(value)) { 22 | return false; 23 | } 24 | self.values.push(value); 25 | self.indexes[value] = self.values.length; 26 | return true; 27 | } 28 | 29 | /// @dev Remove a value from a Set 30 | /// 31 | /// @param self The Set. 32 | /// @param value The value to remove. 33 | /// 34 | /// @return Whether the operation was successful (unsuccessful if the value was not contained in the Set) 35 | function remove(AddressSet storage self, address value) internal returns (bool) { 36 | uint256 index = self.indexes[value]; 37 | if (index == 0) { 38 | return false; 39 | } 40 | 41 | // Normalize the index since we know that the element is in the set. 42 | index--; 43 | 44 | uint256 lastIndex = self.values.length - 1; 45 | 46 | if (index != lastIndex) { 47 | address lastValue = self.values[lastIndex]; 48 | self.values[index] = lastValue; 49 | self.indexes[lastValue] = index + 1; 50 | } 51 | 52 | self.values.pop(); 53 | 54 | delete self.indexes[value]; 55 | 56 | return true; 57 | } 58 | 59 | /// @dev Returns true if the value exists in the Set 60 | /// 61 | /// @param self The Set. 62 | /// @param value The value to check. 63 | /// 64 | /// @return True if the value is contained in the Set, False if it is not. 65 | function contains(AddressSet storage self, address value) internal view returns (bool) { 66 | return self.indexes[value] != 0; 67 | } 68 | } -------------------------------------------------------------------------------- /contracts-hardhat/libraries/Sets.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | /// @title Sets 4 | /// @author Alchemix Finance 5 | library Sets { 6 | using Sets for AddressSet; 7 | 8 | /// @notice A data structure holding an array of values with an index mapping for O(1) lookup. 9 | struct AddressSet { 10 | address[] values; 11 | mapping(address => uint256) indexes; 12 | } 13 | 14 | /// @dev Add a value to a Set 15 | /// 16 | /// @param self The Set. 17 | /// @param value The value to add. 18 | /// 19 | /// @return Whether the operation was successful (unsuccessful if the value is already contained in the Set) 20 | function add(AddressSet storage self, address value) internal returns (bool) { 21 | if (self.contains(value)) { 22 | return false; 23 | } 24 | self.values.push(value); 25 | self.indexes[value] = self.values.length; 26 | return true; 27 | } 28 | 29 | /// @dev Remove a value from a Set 30 | /// 31 | /// @param self The Set. 32 | /// @param value The value to remove. 33 | /// 34 | /// @return Whether the operation was successful (unsuccessful if the value was not contained in the Set) 35 | function remove(AddressSet storage self, address value) internal returns (bool) { 36 | uint256 index = self.indexes[value]; 37 | if (index == 0) { 38 | return false; 39 | } 40 | 41 | // Normalize the index since we know that the element is in the set. 42 | index--; 43 | 44 | uint256 lastIndex = self.values.length - 1; 45 | 46 | if (index != lastIndex) { 47 | address lastValue = self.values[lastIndex]; 48 | self.values[index] = lastValue; 49 | self.indexes[lastValue] = index + 1; 50 | } 51 | 52 | self.values.pop(); 53 | 54 | delete self.indexes[value]; 55 | 56 | return true; 57 | } 58 | 59 | /// @dev Returns true if the value exists in the Set 60 | /// 61 | /// @param self The Set. 62 | /// @param value The value to check. 63 | /// 64 | /// @return True if the value is contained in the Set, False if it is not. 65 | function contains(AddressSet storage self, address value) internal view returns (bool) { 66 | return self.indexes[value] != 0; 67 | } 68 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/curve/IStableMetaPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.5.0; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | /// @dev TODO 7 | uint256 constant N_COINS = 2; 8 | 9 | interface IStableMetaPool is IERC20 { 10 | function get_balances() external view returns (uint256[N_COINS] memory); 11 | 12 | function coins(uint256 index) external view returns (IERC20); 13 | 14 | function A() external view returns (uint256); 15 | 16 | function get_virtual_price() external view returns (uint256); 17 | 18 | function calc_token_amount( 19 | uint256[N_COINS] calldata amounts, 20 | bool deposit 21 | ) external view returns (uint256 amount); 22 | 23 | function add_liquidity( 24 | uint256[N_COINS] calldata amounts, 25 | uint256 minimumMintAmount 26 | ) external returns (uint256 minted); 27 | 28 | function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy); 29 | 30 | function get_dy_underlying(int128 i, int128 j, uint256 dx, uint256[N_COINS] calldata balances) external view returns (uint256 dy); 31 | 32 | function exchange(int128 i, int128 j, uint256 dx, uint256 minimumDy) external returns (uint256); 33 | 34 | function remove_liquidity(uint256 amount, uint256[N_COINS] calldata minimumAmounts) external; 35 | 36 | function remove_liquidity_imbalance( 37 | uint256[N_COINS] calldata amounts, 38 | uint256 maximumBurnAmount 39 | ) external returns (uint256); 40 | 41 | function calc_withdraw_one_coin(uint256 tokenAmount, int128 i) external view returns (uint256); 42 | 43 | function remove_liquidity_one_coin( 44 | uint256 tokenAmount, 45 | int128 i, 46 | uint256 minimumAmount 47 | ) external returns (uint256); 48 | 49 | function get_price_cumulative_last() external view returns (uint256[N_COINS] calldata); 50 | 51 | function block_timestamp_last() external view returns (uint256); 52 | 53 | function get_twap_balances( 54 | uint256[N_COINS] calldata firstBalances, 55 | uint256[N_COINS] calldata lastBalances, 56 | uint256 timeElapsed 57 | ) external view returns (uint256[N_COINS] calldata); 58 | 59 | function get_dy( 60 | int128 i, 61 | int128 j, 62 | uint256 dx, 63 | uint256[N_COINS] calldata balances 64 | ) external view returns (uint256); 65 | } -------------------------------------------------------------------------------- /test-forge/RETHAdapterV1.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity 0.8.13; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | import {stdCheats} from "forge-std/stdlib.sol"; 6 | import "forge-std/console.sol"; 7 | 8 | import { 9 | RETHAdapterV1, 10 | InitializationParams as AdapterInitializationParams 11 | } from "../adapters/rocket/RETHAdapterV1.sol"; 12 | 13 | import {IWETH9} from "../interfaces/external/IWETH9.sol"; 14 | import {IRETH} from "../interfaces/external/rocket/IRETH.sol"; 15 | import {IRocketStorage} from "../interfaces/external/rocket/IRocketStorage.sol"; 16 | 17 | import {RocketPool} from "../libraries/RocketPool.sol"; 18 | import {SafeERC20} from "../libraries/SafeERC20.sol"; 19 | 20 | contract RocketStakedEthereumAdapterV1Test is DSTestPlus, stdCheats { 21 | IWETH9 constant weth = IWETH9(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); 22 | IRocketStorage constant rocketStorage = IRocketStorage(0x1d8f8f00cfa6758d7bE78336684788Fb0ee0Fa46); 23 | 24 | IRETH rETH; 25 | RETHAdapterV1 adapter; 26 | 27 | function setUp() external { 28 | rETH = RocketPool.getRETH(rocketStorage); 29 | 30 | adapter = new RETHAdapterV1(AdapterInitializationParams({ 31 | alchemist: address(this), 32 | token: address(rETH), 33 | underlyingToken: address(weth) 34 | })); 35 | } 36 | 37 | function testPrice() external { 38 | uint256 decimals = SafeERC20.expectDecimals(address(rETH)); 39 | assertEq(adapter.price(), rETH.getEthValue(10**decimals)); 40 | } 41 | 42 | function testWrap() external { 43 | tip(address(weth), address(this), 1e18); 44 | 45 | SafeERC20.safeApprove(address(weth), address(adapter), 1e18); 46 | 47 | expectUnsupportedOperationError("Wrapping is not supported"); 48 | adapter.wrap(1e18, address(0xbeef)); 49 | } 50 | 51 | function testUnwrap() external { 52 | tip(address(rETH), address(this), 1e18); 53 | 54 | uint256 expectedEth = rETH.getEthValue(1e18); 55 | 56 | SafeERC20.safeApprove(address(rETH), address(adapter), 1e18); 57 | uint256 unwrapped = adapter.unwrap(1e18, address(0xbeef)); 58 | 59 | assertEq(rETH.allowance(address(this), address(adapter)), 0); 60 | assertEq(weth.balanceOf(address(0xbeef)), unwrapped); 61 | assertEq(weth.balanceOf(address(0xbeef)), expectedEth); 62 | } 63 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/IWETHGateway.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | /// @title IWETHGateway 4 | /// @author Alchemix Finance 5 | interface IWETHGateway { 6 | /// @notice Refreshes the wrapped ethereum ERC20 approval for an alchemist contract. 7 | /// 8 | /// @param alchemist The address of the alchemist to refresh the allowance for. 9 | function refreshAllowance(address alchemist) external; 10 | 11 | /// @notice Takes ethereum, converts it to wrapped ethereum, and then deposits it into an alchemist. 12 | /// 13 | /// See [IAlchemistV2Actions.depositUnderlying](./alchemist/IAlchemistV2Actions.md#depositunderlying) for more details. 14 | /// 15 | /// @param alchemist The address of the alchemist to deposit wrapped ethereum into. 16 | /// @param yieldToken The yield token to deposit the wrapped ethereum as. 17 | /// @param amount The amount of ethereum to deposit. 18 | /// @param recipient The address which will receive the deposited yield tokens. 19 | /// @param minimumAmountOut The minimum amount of yield tokens that are expected to be deposited to `recipient`. 20 | function depositUnderlying( 21 | address alchemist, 22 | address yieldToken, 23 | uint256 amount, 24 | address recipient, 25 | uint256 minimumAmountOut 26 | ) external payable; 27 | 28 | /// @notice Withdraws a wrapped ethereum based yield token from an alchemist, converts it to ethereum, and then 29 | /// transfers it to the recipient. 30 | /// 31 | /// A withdraw approval on the alchemist is required for this call to succeed. 32 | /// 33 | /// See [IAlchemistV2Actions.withdrawUnderlying](./alchemist/IAlchemistV2Actions.md#withdrawunderlying) for more details. 34 | /// 35 | /// @param alchemist The address of the alchemist to withdraw wrapped ethereum from. 36 | /// @param yieldToken The address of the yield token to withdraw. 37 | /// @param shares The amount of shares to withdraw. 38 | /// @param recipient The address which will receive the ethereum. 39 | /// @param minimumAmountOut The minimum amount of underlying tokens that are expected to be withdrawn to `recipient`. 40 | function withdrawUnderlying( 41 | address alchemist, 42 | address yieldToken, 43 | uint256 shares, 44 | address recipient, 45 | uint256 minimumAmountOut 46 | ) external; 47 | } -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/IWETHGateway.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | /// @title IWETHGateway 4 | /// @author Alchemix Finance 5 | interface IWETHGateway { 6 | /// @notice Refreshes the wrapped ethereum ERC20 approval for an alchemist contract. 7 | /// 8 | /// @param alchemist The address of the alchemist to refresh the allowance for. 9 | function refreshAllowance(address alchemist) external; 10 | 11 | /// @notice Takes ethereum, converts it to wrapped ethereum, and then deposits it into an alchemist. 12 | /// 13 | /// See [IAlchemistV2Actions.depositUnderlying](./alchemist/IAlchemistV2Actions.md#depositunderlying) for more details. 14 | /// 15 | /// @param alchemist The address of the alchemist to deposit wrapped ethereum into. 16 | /// @param yieldToken The yield token to deposit the wrapped ethereum as. 17 | /// @param amount The amount of ethereum to deposit. 18 | /// @param recipient The address which will receive the deposited yield tokens. 19 | /// @param minimumAmountOut The minimum amount of yield tokens that are expected to be deposited to `recipient`. 20 | function depositUnderlying( 21 | address alchemist, 22 | address yieldToken, 23 | uint256 amount, 24 | address recipient, 25 | uint256 minimumAmountOut 26 | ) external payable; 27 | 28 | /// @notice Withdraws a wrapped ethereum based yield token from an alchemist, converts it to ethereum, and then 29 | /// transfers it to the recipient. 30 | /// 31 | /// A withdraw approval on the alchemist is required for this call to succeed. 32 | /// 33 | /// See [IAlchemistV2Actions.withdrawUnderlying](./alchemist/IAlchemistV2Actions.md#withdrawunderlying) for more details. 34 | /// 35 | /// @param alchemist The address of the alchemist to withdraw wrapped ethereum from. 36 | /// @param yieldToken The address of the yield token to withdraw. 37 | /// @param shares The amount of shares to withdraw. 38 | /// @param recipient The address which will receive the ethereum. 39 | /// @param minimumAmountOut The minimum amount of underlying tokens that are expected to be withdrawn to `recipient`. 40 | function withdrawUnderlying( 41 | address alchemist, 42 | address yieldToken, 43 | uint256 shares, 44 | address recipient, 45 | uint256 minimumAmountOut 46 | ) external; 47 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/curve/IEthStableMetaPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.5.0; 3 | 4 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 5 | 6 | uint256 constant N_COINS = 2; 7 | 8 | interface IEthStableMetaPool is IERC20 { 9 | function get_balances() external view returns (uint256[N_COINS] memory); 10 | 11 | function coins(uint256 index) external view returns (IERC20); 12 | 13 | function A() external view returns (uint256); 14 | 15 | function get_virtual_price() external view returns (uint256); 16 | 17 | function calc_token_amount( 18 | uint256[N_COINS] calldata amounts, 19 | bool deposit 20 | ) external view returns (uint256 amount); 21 | 22 | function add_liquidity( 23 | uint256[N_COINS] calldata amounts, 24 | uint256 minimumMintAmount 25 | ) external payable returns (uint256 minted); 26 | 27 | function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy); 28 | 29 | function get_dy_underlying( 30 | int128 i, 31 | int128 j, 32 | uint256 dx, 33 | uint256[N_COINS] calldata balances 34 | ) external view returns (uint256 dy); 35 | 36 | function exchange( 37 | int128 i, 38 | int128 j, 39 | uint256 dx, 40 | uint256 minimumDy 41 | ) external payable returns (uint256); 42 | 43 | function remove_liquidity(uint256 amount, uint256[N_COINS] calldata minimumAmounts) external; 44 | 45 | function remove_liquidity_imbalance( 46 | uint256[N_COINS] calldata amounts, 47 | uint256 maximumBurnAmount 48 | ) external returns (uint256); 49 | 50 | function calc_withdraw_one_coin(uint256 tokenAmount, int128 i) external view returns (uint256); 51 | 52 | function remove_liquidity_one_coin( 53 | uint256 tokenAmount, 54 | int128 i, 55 | uint256 minimumAmount 56 | ) external returns (uint256); 57 | 58 | function get_price_cumulative_last() external view returns (uint256[N_COINS] calldata); 59 | 60 | function block_timestamp_last() external view returns (uint256); 61 | 62 | function get_twap_balances( 63 | uint256[N_COINS] calldata firstBalances, 64 | uint256[N_COINS] calldata lastBalances, 65 | uint256 timeElapsed 66 | ) external view returns (uint256[N_COINS] calldata); 67 | 68 | function get_dy( 69 | int128 i, 70 | int128 j, 71 | uint256 dx, 72 | uint256[N_COINS] calldata balances 73 | ) external view returns (uint256); 74 | } -------------------------------------------------------------------------------- /contracts-full/adapters/yearn/YearnTokenAdapter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import {IllegalState} from "../../base/Errors.sol"; 4 | 5 | import "../../interfaces/ITokenAdapter.sol"; 6 | import "../../interfaces/external/yearn/IYearnVaultV2.sol"; 7 | 8 | import "../../libraries/TokenUtils.sol"; 9 | 10 | /// @title YearnTokenAdapter 11 | /// @author Alchemix Finance 12 | contract YearnTokenAdapter is ITokenAdapter { 13 | uint256 private constant MAXIMUM_SLIPPAGE = 10000; 14 | string public constant override version = "2.1.0"; 15 | 16 | address public immutable override token; 17 | address public immutable override underlyingToken; 18 | 19 | constructor(address _token, address _underlyingToken) { 20 | token = _token; 21 | underlyingToken = _underlyingToken; 22 | } 23 | 24 | /// @inheritdoc ITokenAdapter 25 | function price() external view override returns (uint256) { 26 | return IYearnVaultV2(token).pricePerShare(); 27 | } 28 | 29 | /// @inheritdoc ITokenAdapter 30 | function wrap(uint256 amount, address recipient) external override returns (uint256) { 31 | TokenUtils.safeTransferFrom(underlyingToken, msg.sender, address(this), amount); 32 | TokenUtils.safeApprove(underlyingToken, token, amount); 33 | 34 | return IYearnVaultV2(token).deposit(amount, recipient); 35 | } 36 | 37 | /// @inheritdoc ITokenAdapter 38 | function unwrap(uint256 amount, address recipient) external override returns (uint256) { 39 | TokenUtils.safeTransferFrom(token, msg.sender, address(this), amount); 40 | 41 | uint256 balanceBefore = TokenUtils.safeBalanceOf(token, address(this)); 42 | 43 | uint256 amountWithdrawn = IYearnVaultV2(token).withdraw(amount, recipient, MAXIMUM_SLIPPAGE); 44 | 45 | uint256 balanceAfter = TokenUtils.safeBalanceOf(token, address(this)); 46 | 47 | // If the Yearn vault did not burn all of the shares then revert. This is critical in mathematical operations 48 | // performed by the system because the system always expects that all of the tokens were unwrapped. In Yearn, 49 | // this sometimes does not happen in cases where strategies cannot withdraw all of the requested tokens (an 50 | // example strategy where this can occur is with Compound and AAVE where funds may not be accessible because 51 | // they were lent out). 52 | if (balanceBefore - balanceAfter != amount) { 53 | revert IllegalState(); 54 | } 55 | 56 | return amountWithdrawn; 57 | } 58 | } -------------------------------------------------------------------------------- /contracts-full/interfaces/external/aave/ILendingPoolAddressesProvider.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title ILendingPoolAddressesProvider 5 | /// @author Aave 6 | /// 7 | /// @dev Main registry of addresses part of or connected to the protocol, including permissioned roles. 8 | /// 9 | /// - Acting also as factory of proxies and admin of those, so with right to change its implementations. 10 | /// - Owned by the Aave Governance. 11 | interface ILendingPoolAddressesProvider { 12 | event MarketIdSet(string newMarketId); 13 | event LendingPoolUpdated(address indexed newAddress); 14 | event ConfigurationAdminUpdated(address indexed newAddress); 15 | event EmergencyAdminUpdated(address indexed newAddress); 16 | event LendingPoolConfiguratorUpdated(address indexed newAddress); 17 | event LendingPoolCollateralManagerUpdated(address indexed newAddress); 18 | event PriceOracleUpdated(address indexed newAddress); 19 | event LendingRateOracleUpdated(address indexed newAddress); 20 | event ProxyCreated(bytes32 id, address indexed newAddress); 21 | event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy); 22 | 23 | function getMarketId() external view returns (string memory); 24 | 25 | function setMarketId(string calldata marketId) external; 26 | 27 | function setAddress(bytes32 id, address newAddress) external; 28 | 29 | function setAddressAsProxy(bytes32 id, address impl) external; 30 | 31 | function getAddress(bytes32 id) external view returns (address); 32 | 33 | function getLendingPool() external view returns (address); 34 | 35 | function setLendingPoolImpl(address pool) external; 36 | 37 | function getLendingPoolConfigurator() external view returns (address); 38 | 39 | function setLendingPoolConfiguratorImpl(address configurator) external; 40 | 41 | function getLendingPoolCollateralManager() external view returns (address); 42 | 43 | function setLendingPoolCollateralManager(address manager) external; 44 | 45 | function getPoolAdmin() external view returns (address); 46 | 47 | function setPoolAdmin(address admin) external; 48 | 49 | function getEmergencyAdmin() external view returns (address); 50 | 51 | function setEmergencyAdmin(address admin) external; 52 | 53 | function getPriceOracle() external view returns (address); 54 | 55 | function setPriceOracle(address priceOracle) external; 56 | 57 | function getLendingRateOracle() external view returns (address); 58 | 59 | function setLendingRateOracle(address lendingRateOracle) external; 60 | } 61 | -------------------------------------------------------------------------------- /contracts-hardhat/adapters/yearn/YearnTokenAdapter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.11; 2 | 3 | import {IllegalState} from "../../base/Errors.sol"; 4 | 5 | import "../../interfaces/ITokenAdapter.sol"; 6 | import "../../interfaces/external/yearn/IYearnVaultV2.sol"; 7 | 8 | import "../../libraries/TokenUtils.sol"; 9 | 10 | /// @title YearnTokenAdapter 11 | /// @author Alchemix Finance 12 | contract YearnTokenAdapter is ITokenAdapter { 13 | uint256 private constant MAXIMUM_SLIPPAGE = 10000; 14 | string public constant override version = "2.1.0"; 15 | 16 | address public immutable override token; 17 | address public immutable override underlyingToken; 18 | 19 | constructor(address _token, address _underlyingToken) { 20 | token = _token; 21 | underlyingToken = _underlyingToken; 22 | } 23 | 24 | /// @inheritdoc ITokenAdapter 25 | function price() external view override returns (uint256) { 26 | return IYearnVaultV2(token).pricePerShare(); 27 | } 28 | 29 | /// @inheritdoc ITokenAdapter 30 | function wrap(uint256 amount, address recipient) external override returns (uint256) { 31 | TokenUtils.safeTransferFrom(underlyingToken, msg.sender, address(this), amount); 32 | TokenUtils.safeApprove(underlyingToken, token, amount); 33 | 34 | return IYearnVaultV2(token).deposit(amount, recipient); 35 | } 36 | 37 | /// @inheritdoc ITokenAdapter 38 | function unwrap(uint256 amount, address recipient) external override returns (uint256) { 39 | TokenUtils.safeTransferFrom(token, msg.sender, address(this), amount); 40 | 41 | uint256 balanceBefore = TokenUtils.safeBalanceOf(token, address(this)); 42 | 43 | uint256 amountWithdrawn = IYearnVaultV2(token).withdraw(amount, recipient, MAXIMUM_SLIPPAGE); 44 | 45 | uint256 balanceAfter = TokenUtils.safeBalanceOf(token, address(this)); 46 | 47 | // If the Yearn vault did not burn all of the shares then revert. This is critical in mathematical operations 48 | // performed by the system because the system always expects that all of the tokens were unwrapped. In Yearn, 49 | // this sometimes does not happen in cases where strategies cannot withdraw all of the requested tokens (an 50 | // example strategy where this can occur is with Compound and AAVE where funds may not be accessible because 51 | // they were lent out). 52 | if (balanceBefore - balanceAfter != amount) { 53 | revert IllegalState(); 54 | } 55 | 56 | return amountWithdrawn; 57 | } 58 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AlchemixV2", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "engines": { 7 | "node": "^16.0.0" 8 | }, 9 | "devDependencies": { 10 | "@eth-optimism/smock": "^1.1.10", 11 | "@nomiclabs/hardhat-ethers": "^2.0.5", 12 | "@nomiclabs/hardhat-etherscan": "^2.1.3", 13 | "@nomiclabs/hardhat-waffle": "^2.0.0", 14 | "@openzeppelin/contracts": "^4.3.2", 15 | "@openzeppelin/hardhat-upgrades": "^1.14.0", 16 | "@studydefi/money-legos": "^2.4.2", 17 | "@typechain/ethers-v5": "^7.0.1", 18 | "@typechain/hardhat": "^2.3.0", 19 | "@types/chai": "^4.2.21", 20 | "@types/mocha": "^9.0.0", 21 | "@types/node": "^16.4.13", 22 | "@typescript-eslint/eslint-plugin": "^4.29.1", 23 | "@typescript-eslint/parser": "^4.29.1", 24 | "chai": "^4.2.0", 25 | "dotenv": "^10.0.0", 26 | "eslint": "^7.29.0", 27 | "eslint-config-prettier": "^8.3.0", 28 | "eslint-config-standard": "^16.0.3", 29 | "eslint-plugin-import": "^2.23.4", 30 | "eslint-plugin-node": "^11.1.0", 31 | "eslint-plugin-prettier": "^3.4.0", 32 | "eslint-plugin-promise": "^5.1.0", 33 | "ethereum-waffle": "^3.0.0", 34 | "ethereumjs-util": "^7.1.3", 35 | "ethers": "^5.6.1", 36 | "hardhat": "^2.9.2", 37 | "hardhat-contract-sizer": "^2.1.1", 38 | "hardhat-deploy": "^0.11.4", 39 | "hardhat-gas-reporter": "^1.0.4", 40 | "prettier": "^2.3.2", 41 | "prettier-plugin-solidity": "^1.0.0-beta.13", 42 | "solc": "0.8.11", 43 | "solhint": "^3.3.6", 44 | "solidity-coverage": "^0.7.16", 45 | "ts-node": "^10.1.0", 46 | "typechain": "^5.1.2", 47 | "typescript": "^4.3.5" 48 | }, 49 | "scripts": { 50 | "compile": "npx hardhat compile", 51 | "coverage": "npx hardhat coverage", 52 | "docgen": "npx hardhat docgen", 53 | "fork": "cp -r deployments/mainnet/ deployments/localhost/; cp -r deployments/v1/ deployments/localhost/; echo 1337 > deployments/localhost/.chainId; cp ./.openzeppelin/mainnet.json ./.openzeppelin/localhost.json; cp ./.openzeppelin/mainnet.json ./.openzeppelin/unknown-1337.json;", 54 | "startnode": "npx hardhat node --no-deploy", 55 | "prettier": "prettier --write 'contracts/**/*.sol'", 56 | "test": "npx hardhat test", 57 | "typechain": "npx hardhat typechain" 58 | }, 59 | "dependencies": { 60 | "@openzeppelin/contracts-upgradeable": "^4.4.2", 61 | "@rari-capital/solmate": "^6.2.0", 62 | "chalk": "4.1.2", 63 | "moment": "^2.29.1", 64 | "solidity-docgen": "^0.5.16" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /contracts-hardhat/interfaces/external/aave/ILendingPoolAddressesProvider.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.5.0; 3 | 4 | /// @title ILendingPoolAddressesProvider 5 | /// @author Aave 6 | /// 7 | /// @dev Main registry of addresses part of or connected to the protocol, including permissioned roles. 8 | /// 9 | /// - Acting also as factory of proxies and admin of those, so with right to change its implementations. 10 | /// - Owned by the Aave Governance. 11 | interface ILendingPoolAddressesProvider { 12 | event MarketIdSet(string newMarketId); 13 | event LendingPoolUpdated(address indexed newAddress); 14 | event ConfigurationAdminUpdated(address indexed newAddress); 15 | event EmergencyAdminUpdated(address indexed newAddress); 16 | event LendingPoolConfiguratorUpdated(address indexed newAddress); 17 | event LendingPoolCollateralManagerUpdated(address indexed newAddress); 18 | event PriceOracleUpdated(address indexed newAddress); 19 | event LendingRateOracleUpdated(address indexed newAddress); 20 | event ProxyCreated(bytes32 id, address indexed newAddress); 21 | event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy); 22 | 23 | function getMarketId() external view returns (string memory); 24 | 25 | function setMarketId(string calldata marketId) external; 26 | 27 | function setAddress(bytes32 id, address newAddress) external; 28 | 29 | function setAddressAsProxy(bytes32 id, address impl) external; 30 | 31 | function getAddress(bytes32 id) external view returns (address); 32 | 33 | function getLendingPool() external view returns (address); 34 | 35 | function setLendingPoolImpl(address pool) external; 36 | 37 | function getLendingPoolConfigurator() external view returns (address); 38 | 39 | function setLendingPoolConfiguratorImpl(address configurator) external; 40 | 41 | function getLendingPoolCollateralManager() external view returns (address); 42 | 43 | function setLendingPoolCollateralManager(address manager) external; 44 | 45 | function getPoolAdmin() external view returns (address); 46 | 47 | function setPoolAdmin(address admin) external; 48 | 49 | function getEmergencyAdmin() external view returns (address); 50 | 51 | function setEmergencyAdmin(address admin) external; 52 | 53 | function getPriceOracle() external view returns (address); 54 | 55 | function setPriceOracle(address priceOracle) external; 56 | 57 | function getLendingRateOracle() external view returns (address); 58 | 59 | function setLendingRateOracle(address lendingRateOracle) external; 60 | } 61 | -------------------------------------------------------------------------------- /test-forge/WstETHAdapterV1.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity 0.8.13; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | import {stdCheats} from "forge-std/stdlib.sol"; 6 | 7 | import { 8 | WstETHAdapterV1, 9 | InitializationParams as AdapterInitializationParams 10 | } from "../adapters/lido/WstETHAdapterV1.sol"; 11 | 12 | import {IWETH9} from "../interfaces/external/IWETH9.sol"; 13 | import {IStableSwap2Pool} from "../interfaces/external/curve/IStableSwap2Pool.sol"; 14 | import {IStETH} from "../interfaces/external/lido/IStETH.sol"; 15 | import {IWstETH} from "../interfaces/external/lido/IWstETH.sol"; 16 | 17 | import {SafeERC20} from "../libraries/SafeERC20.sol"; 18 | 19 | contract WstETHAdapterV1Test is DSTestPlus, stdCheats { 20 | IStETH constant stETH = IStETH(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84); 21 | IWstETH constant wstETH = IWstETH(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0); 22 | IWETH9 constant weth = IWETH9(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); 23 | IStableSwap2Pool constant curvePool = IStableSwap2Pool(0xDC24316b9AE028F1497c275EB9192a3Ea0f67022); 24 | 25 | WstETHAdapterV1 adapter; 26 | 27 | function setUp() external { 28 | adapter = new WstETHAdapterV1(AdapterInitializationParams({ 29 | alchemist: address(this), 30 | token: address(wstETH), 31 | parentToken: address(stETH), 32 | underlyingToken: address(weth), 33 | curvePool: address(curvePool), 34 | ethPoolIndex: 0, 35 | stEthPoolIndex: 1, 36 | referral: address(0) 37 | })); 38 | } 39 | 40 | function testPrice() external { 41 | uint256 decimals = SafeERC20.expectDecimals(address(wstETH)); 42 | assertEq(adapter.price(), stETH.getPooledEthByShares(10**decimals)); 43 | } 44 | 45 | function testWrap() external { 46 | tip(address(weth), address(this), 1e18); 47 | 48 | SafeERC20.safeApprove(address(weth), address(adapter), 1e18); 49 | uint256 wrapped = adapter.wrap(1e18, address(0xbeef)); 50 | 51 | assertEq(weth.allowance(address(this), address(adapter)), 0); 52 | assertEq(wstETH.balanceOf(address(0xbeef)), wrapped); 53 | } 54 | 55 | function testUnwrap() external { 56 | tip(address(wstETH), address(this), 1e18); 57 | 58 | SafeERC20.safeApprove(address(wstETH), address(adapter), 1e18); 59 | uint256 unwrapped = adapter.unwrap(1e18, address(0xbeef)); 60 | 61 | assertEq(wstETH.allowance(address(this), address(adapter)), 0); 62 | assertEq(weth.balanceOf(address(0xbeef)), unwrapped); 63 | } 64 | } -------------------------------------------------------------------------------- /contracts-full/libraries/LibFuse.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.13; 3 | 4 | import {FixedPointMathLib} from "./solmate/FixedPointMathLib.sol"; 5 | 6 | import {ICERC20} from "../interfaces/external/compound/ICERC20.sol"; 7 | import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; 8 | 9 | /// @notice Get up to date cToken data without mutating state. 10 | /// @author Transmissions11 (https://github.com/transmissions11/libcompound) 11 | library LibFuse { 12 | using FixedPointMathLib for uint256; 13 | 14 | function viewUnderlyingBalanceOf(ICERC20 cToken, address user) internal view returns (uint256) { 15 | return cToken.balanceOf(user).mulWadDown(viewExchangeRate(cToken)); 16 | } 17 | 18 | function viewExchangeRate(ICERC20 cToken) internal view returns (uint256) { 19 | uint256 accrualBlockNumberPrior = cToken.accrualBlockNumber(); 20 | 21 | if (accrualBlockNumberPrior == block.number) return cToken.exchangeRateStored(); 22 | 23 | uint256 totalCash = IERC20(cToken.underlying()).balanceOf(address(cToken)); 24 | uint256 borrowsPrior = cToken.totalBorrows(); 25 | uint256 reservesPrior = cToken.totalReserves(); 26 | uint256 adminFeesPrior = cToken.totalAdminFees(); 27 | uint256 fuseFeesPrior = cToken.totalFuseFees(); 28 | 29 | uint256 interestAccumulated; // Generated in new scope to avoid stack too deep. 30 | { 31 | uint256 borrowRateMantissa = cToken.interestRateModel().getBorrowRate( 32 | totalCash, 33 | borrowsPrior, 34 | reservesPrior + adminFeesPrior + fuseFeesPrior 35 | ); 36 | 37 | // Same as borrowRateMaxMantissa in CTokenInterfaces.sol 38 | require(borrowRateMantissa <= 0.0005e16, "RATE_TOO_HIGH"); 39 | 40 | interestAccumulated = (borrowRateMantissa * (block.number - accrualBlockNumberPrior)).mulWadDown( 41 | borrowsPrior 42 | ); 43 | } 44 | 45 | uint256 totalReserves = cToken.reserveFactorMantissa().mulWadDown(interestAccumulated) + reservesPrior; 46 | uint256 totalAdminFees = cToken.adminFeeMantissa().mulWadDown(interestAccumulated) + adminFeesPrior; 47 | uint256 totalFuseFees = cToken.fuseFeeMantissa().mulWadDown(interestAccumulated) + fuseFeesPrior; 48 | 49 | uint256 totalSupply = cToken.totalSupply(); 50 | 51 | return 52 | totalSupply == 0 53 | ? cToken.initialExchangeRateMantissa() 54 | : (totalCash + (interestAccumulated + borrowsPrior) - (totalReserves + totalAdminFees + totalFuseFees)) 55 | .divWadDown(totalSupply); 56 | } 57 | } -------------------------------------------------------------------------------- /utils/helpers.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber, BigNumberish, ethers, utils } from "ethers"; 2 | import * as moment from "moment"; 3 | 4 | export const ONE = BigNumber.from(1); 5 | export const MAXIMUM_U32 = ONE.shl(31); 6 | export const MAXIMUM_U256 = ONE.shl(255); 7 | export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; 8 | 9 | export const snapshot = async ( 10 | provider: ethers.providers.JsonRpcProvider 11 | ): Promise => { 12 | await provider.send("evm_snapshot", []); 13 | return await mine(provider); 14 | }; 15 | 16 | export const revert = async ( 17 | provider: ethers.providers.JsonRpcProvider, 18 | snapshotId: number 19 | ): Promise => { 20 | return await provider.send("evm_revert", [snapshotId]); 21 | }; 22 | 23 | export const increaseTime = async ( 24 | provider: ethers.providers.JsonRpcProvider, 25 | seconds: number 26 | ): Promise => { 27 | return provider.send("evm_increaseTime", [seconds]); 28 | }; 29 | 30 | export const setNextBlockTime = async ( 31 | provider: ethers.providers.JsonRpcProvider, 32 | time: moment.Moment 33 | ): Promise => { 34 | return provider.send("evm_setNextBlockTimestamp", [time.unix()]); 35 | }; 36 | 37 | export const mine = async ( 38 | provider: ethers.providers.JsonRpcProvider 39 | ): Promise => { 40 | return provider.send("evm_mine", []); 41 | }; 42 | 43 | export const mineBlocks = async ( 44 | provider: ethers.providers.JsonRpcProvider, 45 | numberBlocks: number 46 | ): Promise => { 47 | for (let i = 0; i < numberBlocks; i++) { 48 | await provider.send("evm_mine", []); 49 | } 50 | return Promise.resolve(); 51 | }; 52 | 53 | export const feeOn = ( 54 | value: BigNumberish, 55 | numerator: BigNumberish, 56 | resolution: BigNumberish 57 | ): BigNumber => { 58 | return ONE.mul(value).mul(numerator).div(resolution); 59 | }; 60 | 61 | export const takeFee = ( 62 | value: BigNumberish, 63 | numerator: BigNumberish, 64 | resolution: BigNumberish 65 | ): BigNumber => { 66 | return ONE.mul(value).sub(feeOn(value, numerator, resolution)); 67 | }; 68 | 69 | export const delay = (ms: number) => new Promise((res) => setTimeout(res, ms)); 70 | 71 | // export const getGas = async (tx) => { 72 | // let resp = await tx.wait(1); 73 | // console.log(resp); 74 | // return resp.gasUsed; 75 | // }; 76 | 77 | export const parseUsdc = (usdc: string): BigNumber => { 78 | return utils.parseUnits(usdc, 6); 79 | }; 80 | 81 | export const formatUsdc = (usdcents: BigNumberish): string => { 82 | return utils.formatUnits(usdcents, 6); 83 | }; 84 | 85 | export const generateRandomHex = (size: number) => 86 | [...Array(size)] 87 | .map(() => Math.floor(Math.random() * 16).toString(16)) 88 | .join(""); -------------------------------------------------------------------------------- /contracts-full/test/TransmuterMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity ^0.8.11; 3 | 4 | import "@openzeppelin/contracts/utils/Context.sol"; 5 | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 6 | import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; 7 | import "@openzeppelin/contracts/utils/math/SafeMath.sol"; 8 | import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 9 | import {ITransmuterBuffer} from "../interfaces/transmuter/ITransmuterBuffer.sol"; 10 | 11 | contract TransmuterMock is Context, ReentrancyGuard { 12 | using SafeMath for uint256; 13 | using SafeERC20 for IERC20Upgradeable; 14 | 15 | address public constant ZERO_ADDRESS = address(0); 16 | uint256 public TRANSMUTATION_PERIOD; 17 | 18 | address public alToken; 19 | address public underlyingToken; 20 | 21 | uint256 public totalExchanged; 22 | 23 | address public collateralSource; 24 | 25 | /// @dev alchemist addresses whitelisted 26 | mapping(address => bool) public whiteList; 27 | 28 | /// @dev The address of the account which currently has administrative capabilities over this contract. 29 | address public governance; 30 | 31 | event Distribution(address origin, address underlying, uint256 amount); 32 | 33 | event WhitelistSet(address whitelisted, bool state); 34 | 35 | constructor( 36 | address _alToken, 37 | address _underlyingToken, 38 | address _collateralSource 39 | ) { 40 | governance = msg.sender; 41 | alToken = _alToken; 42 | underlyingToken = _underlyingToken; 43 | collateralSource = _collateralSource; 44 | TRANSMUTATION_PERIOD = 50; 45 | } 46 | 47 | /// @dev A modifier which checks if whitelisted for minting. 48 | modifier onlyWhitelisted() { 49 | require(whiteList[msg.sender], "Transmuter: !whitelisted"); 50 | _; 51 | } 52 | 53 | /// @dev Checks that the current message sender or caller is the governance address. 54 | /// 55 | /// 56 | modifier onlyGov() { 57 | require(msg.sender == governance, "Transmuter: !governance"); 58 | _; 59 | } 60 | 61 | /// @dev Sets the whitelist 62 | /// 63 | /// This function reverts if the caller is not governance 64 | /// 65 | /// @param _toWhitelist the account to mint underlyingTokens to. 66 | /// @param _state the whitelist state. 67 | function setWhitelist(address _toWhitelist, bool _state) external onlyGov { 68 | whiteList[_toWhitelist] = _state; 69 | emit WhitelistSet(_toWhitelist, _state); 70 | } 71 | 72 | function exchange(uint256 amount) external { 73 | totalExchanged += amount; 74 | } 75 | 76 | function claim( 77 | uint256 amount, 78 | address recipient 79 | ) external { 80 | ITransmuterBuffer(collateralSource).withdraw(underlyingToken, amount, recipient); 81 | } 82 | } 83 | --------------------------------------------------------------------------------