├── 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 |
--------------------------------------------------------------------------------