diff --git a/.solhint.json b/.solhint.json index c405fa32..fb9add9d 100755 --- a/.solhint.json +++ b/.solhint.json @@ -13,10 +13,13 @@ ], "compiler-version": [ "error", - "0.6.4" + "0.6.5" ], "private-vars-leading-underscore": [ "off" + ], + "const-name-snakecase": [ + "off" ] } } diff --git a/.soliumignore b/.soliumignore index d9ec197b..dd775dfa 100755 --- a/.soliumignore +++ b/.soliumignore @@ -7,5 +7,8 @@ node_modules ./contracts/ProtocolManager.sol ./contracts/Ownable.sol ./contracts/adapters/maker/MKRAdapter.sol -./contracts/adapters/uniswap/UniswapTokenAdapter.sol +./contracts/adapters/uniswap/UniswapV1TokenAdapter.sol +./contracts/adapters/balancer/BalancerTokenAdapter.sol ./contracts/adapters/dydx +./contracts/adapters +./contracts/mock diff --git a/README.md b/README.md index 003e9c29..ce1c501f 100755 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ [![Coverage status](https://github.com/zeriontech/protocol-wrappers/workflows/coverage/badge.svg)](https://github.com/zeriontech/defi-sdk/actions?query=workflow:coverage) [![Lint status](https://github.com/zeriontech/protocol-wrappers/workflows/lint/badge.svg)](https://github.com/zeriontech/defi-sdk/actions?query=workflow:lint) [![License](https://img.shields.io/github/license/zeriontech/defi-sdk)](https://www.gnu.org/licenses/lgpl-3.0.en.html) -[![Discord](https://img.shields.io/discord/544761450724458498?label=discord)](https://go.zerion.io/discord) -[![Twitter Follow](https://img.shields.io/twitter/follow/zerion_io.svg)](https://twitter.com/intent/follow?screen_name=zerion_io) +[![Discord](https://badgen.net/badge/zerion/Zerion?icon=discord&label=discord)](https://go.zerion.io/discord) +[![Twitter Follow](https://badgen.net/twitter/follow/zerion_io)](https://twitter.com/intent/follow?screen_name=zerion_io) **DeFi SDK** is an open-source system of smart contracts designed for precise DeFi portfolio accounting. To put it simply, DeFi SDK is the on-chain *balanceOf* for DeFi protocols. @@ -140,7 +140,7 @@ and obtain all balances for a given account. The response from the smart-contrac ... ``` -## DeFi SDK architecture +## DeFi SDK Architecture - **ProtocolAdapter** is a special contract for every protocol. Its main purpose is to wrap all the protocol interactions. There are different types of protocol adapters: "Asset" adapter returns the amount of the account's tokens held on the protocol and the "Debt" adapter returns the amount of the account's debt to the protocol. Some protocols do not use "simple" ERC20 tokens but instead have complex derivatives, for example the Compound protocol has CTokens. The **ProtocolAdapter** contract also provides information about the type of tokens used within it. @@ -150,11 +150,12 @@ Its main purpose is to provide ERC20-style token metadata as well as information More detailed documentation about contracts can be found in [adapters](../../wiki/Adapters) and [AdapterRegistry](../../wiki/AdapterRegistry) documentation. -## Supported protocols +## Supported Protocols | Protocol Name | Description | Protocol Adapters | Token Adapters | | :-----------: | :---------: | :---------------: | :------------: | | [Aave](./contracts/adapters/aave) | Decentralized lending & borrowing protocol. | [Asset adapter](./contracts/adapters/aave/AaveAssetAdapter.sol)
[Debt adapter](contracts/adapters/aave/AaveDebtAdapter.sol) | ["AToken"](./contracts/adapters/aave/AaveTokenAdapter.sol) | +| [Balancer](./contracts/adapters/balancer) | Non-custodial portfolio manager, liquidity provider, and price sensor. | [Asset adapter](./contracts/adapters/balancer/BalancerAdapter.sol) supports all Balancer pools | ["Balancer pool token"](./contracts/adapters/aave/BalancerTokenAdapter.sol) | | [Compound](./contracts/adapters/compound) | Decentralized lending & borrowing protocol. | [Asset adapter](./contracts/adapters/compound/CompoundAssetAdapter.sol)
[Debt adapter](./contracts/adapters/compound/CompoundDebtAdapter.sol) | ["CToken"](./contracts/adapters/compound/CompoundTokenAdapter.sol) | | [Curve](./contracts/adapters/curve) | Exchange liquidity pool for stablecoin trading. Supports Compound, Y, and BUSD pools. | [Asset adapter](./contracts/adapters/curve/CurveAdapter.sol) | ["Curve pool token"](contracts/adapters/curve/CurveTokenAdapter.sol) | | [dYdX](./contracts/adapters/dydx) | Decentralized trading platform. All 4 markets (WETH, SAI, USDC, DAI) are supported. | [Asset adapter](./contracts/adapters/dydx/DyDxAssetAdapter.sol)
[Debt adapter](./contracts/adapters/dydx/DyDxDebtAdapter.sol) | — | @@ -168,14 +169,14 @@ More detailed documentation about contracts can be found in [adapters](../../wik | [Uniswap V1](./contracts/adapters/uniswap) | Automated liquidity protocol. Top 30 pools are added to the **AdapterRegistry** contract, however adapter supports all Uniswap pools. | [Asset adapter](./contracts/adapters/uniswap/UniswapV1Adapter.sol) supports all Uniswap pools | ["Uniswap V1 pool token"](./contracts/adapters/uniswap/UniswapV1TokenAdapter.sol) | | [0x Staking](./contracts/adapters/zrx) | Liquidity rewards for staking ZRX. | [Asset adapter](./contracts/adapters/zrx/ZrxAdapter.sol) | — | -## How to add your adapter +## How to Add Your Adapter The full instructions on how to add a custom adapter to the **AdapterRegistry** contract may be found in our [wiki](../../wiki/Adding-new-adapters). If you have questions and/or want to add your adapter to Zerion reach out to us on our [Discord server](https://go.zerion.io/discord). -## What’s next for DeFi SDK? 🚀 +## What’s Next for DeFi SDK? 🚀 This first version of DeFi SDK is for read-only accounting purposes. Our next step is to introduce Interactive Adapters that allow users to make cross-protocol transactions from a single interface. We are incredibly excited to work with developers, users and the wider DeFi community to make these integrations as secure and accessible as possible. Watch this space, because the “De” in DeFi is about to get a whole lot more user-friendly! @@ -183,7 +184,7 @@ This first version of DeFi SDK is for read-only accounting purposes. Our next st If you discover a security vulnerability within DeFi SDK, please send us an e-mail at inbox@zerion.io. All security vulnerabilities will be promptly addressed. -## Dev notes +## Dev Notes This project uses Truffle and web3js for all Ethereum interactions and testing. @@ -217,4 +218,4 @@ Currently, unsupported files are ignored. ## License -All smart contracts are released under LGPL v.3. +All smart contracts are released under GNU LGPLv3. diff --git a/contracts/AdapterRegistry.sol b/contracts/AdapterRegistry.sol index 4f3efb68..64874617 100755 --- a/contracts/AdapterRegistry.sol +++ b/contracts/AdapterRegistry.sol @@ -13,15 +13,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { Ownable } from "./Ownable.sol"; -import { ProtocolManager } from "./ProtocolManager.sol"; -import { TokenAdapterManager } from "./TokenAdapterManager.sol"; -import { ProtocolAdapter } from "./adapters/ProtocolAdapter.sol"; -import { TokenAdapter } from "./adapters/TokenAdapter.sol"; -import { Strings } from "./Strings.sol"; import { ProtocolBalance, ProtocolMetadata, @@ -32,6 +26,12 @@ import { TokenMetadata, Component } from "./Structs.sol"; +import { Strings } from "./Strings.sol"; +import { Ownable } from "./Ownable.sol"; +import { ProtocolManager } from "./ProtocolManager.sol"; +import { TokenAdapterManager } from "./TokenAdapterManager.sol"; +import { ProtocolAdapter } from "./adapters/ProtocolAdapter.sol"; +import { TokenAdapter } from "./adapters/TokenAdapter.sol"; /** @@ -107,15 +107,29 @@ contract AdapterRegistry is Ownable, ProtocolManager, TokenAdapterManager { returns (ProtocolBalance[] memory) { ProtocolBalance[] memory protocolBalances = new ProtocolBalance[](protocolNames.length); + uint256 counter = 0; for (uint256 i = 0; i < protocolNames.length; i++) { protocolBalances[i] = ProtocolBalance({ metadata: protocolMetadata[protocolNames[i]], adapterBalances: getAdapterBalances(account, protocolAdapters[protocolNames[i]]) }); + if (protocolBalances[i].adapterBalances.length > 0) { + counter++; + } } - return protocolBalances; + ProtocolBalance[] memory nonZeroProtocolBalances = new ProtocolBalance[](counter); + counter = 0; + + for (uint256 i = 0; i < protocolNames.length; i++) { + if (protocolBalances[i].adapterBalances.length > 0) { + nonZeroProtocolBalances[counter] = protocolBalances[i]; + counter++; + } + } + + return nonZeroProtocolBalances; } /** @@ -132,6 +146,7 @@ contract AdapterRegistry is Ownable, ProtocolManager, TokenAdapterManager { returns (AdapterBalance[] memory) { AdapterBalance[] memory adapterBalances = new AdapterBalance[](adapters.length); + uint256 counter = 0; for (uint256 i = 0; i < adapterBalances.length; i++) { adapterBalances[i] = getAdapterBalance( @@ -139,9 +154,22 @@ contract AdapterRegistry is Ownable, ProtocolManager, TokenAdapterManager { adapters[i], supportedTokens[adapters[i]] ); + if (adapterBalances[i].balances.length > 0) { + counter++; + } + } + + AdapterBalance[] memory nonZeroAdapterBalances = new AdapterBalance[](counter); + counter = 0; + + for (uint256 i = 0; i < adapterBalances.length; i++) { + if (adapterBalances[i].balances.length > 0) { + nonZeroAdapterBalances[counter] = adapterBalances[i]; + counter++; + } } - return adapterBalances; + return nonZeroAdapterBalances; } /** @@ -159,25 +187,34 @@ contract AdapterRegistry is Ownable, ProtocolManager, TokenAdapterManager { view returns (AdapterBalance memory) { - FullTokenBalance[] memory finalFullTokenBalances = new FullTokenBalance[](tokens.length); - uint256 amount; - string memory tokenType; + string memory tokenType = ProtocolAdapter(adapter).tokenType(); + uint256[] memory amounts = new uint256[](tokens.length); + uint256 counter; - for (uint256 i = 0; i < tokens.length; i++) { + for (uint256 i = 0; i < amounts.length; i++) { try ProtocolAdapter(adapter).getBalance(tokens[i], account) returns (uint256 result) { - amount = result; + amounts[i] = result; } catch { - amount = 0; + amounts[i] = 0; } + if (amounts[i] > 0) { + counter++; + } + } - tokenType = ProtocolAdapter(adapter).tokenType(); - - finalFullTokenBalances[i] = getFullTokenBalance( - tokenType, - tokens[i], - amount, - getFinalComponents(tokenType, tokens[i], 1e18) - ); + FullTokenBalance[] memory finalFullTokenBalances = new FullTokenBalance[](counter); + counter = 0; + + for (uint256 i = 0; i < amounts.length; i++) { + if (amounts[i] > 0) { + finalFullTokenBalances[counter] = getFullTokenBalance( + tokenType, + tokens[i], + amounts[i], + getFinalComponents(tokenType, tokens[i], amounts[i]) + ); + counter++; + } } return AdapterBalance({ @@ -212,7 +249,7 @@ contract AdapterRegistry is Ownable, ProtocolManager, TokenAdapterManager { componentTokenBalances[i] = getTokenBalance( components[i].tokenType, components[i].token, - components[i].rate * amount / 1e18 + components[i].rate ); } @@ -237,10 +274,7 @@ contract AdapterRegistry is Ownable, ProtocolManager, TokenAdapterManager { view returns (Component[] memory) { - uint256 totalLength; - - totalLength = getFinalComponentsNumber(tokenType, token, true); - + uint256 totalLength = getFinalComponentsNumber(tokenType, token, true); Component[] memory finalTokens = new Component[](totalLength); uint256 length; uint256 init = 0; @@ -287,13 +321,13 @@ contract AdapterRegistry is Ownable, ProtocolManager, TokenAdapterManager { view returns (uint256) { - if (tokenType.isEqualTo("ERC20")) { - return initial ? uint256(0) : uint256(1); - } - uint256 totalLength = 0; Component[] memory components = getComponents(tokenType, token, 1e18); + if (components.length == 0) { + return initial ? uint256(0) : uint256(1); + } + for (uint256 i = 0; i < components.length; i++) { totalLength = totalLength + getFinalComponentsNumber( components[i].tokenType, @@ -323,9 +357,13 @@ contract AdapterRegistry is Ownable, ProtocolManager, TokenAdapterManager { TokenAdapter adapter = TokenAdapter(tokenAdapter[tokenType]); Component[] memory components; - try adapter.getComponents(token) returns (Component[] memory result) { - components = result; - } catch { + if (address(adapter) != address(0)) { + try adapter.getComponents(token) returns (Component[] memory result) { + components = result; + } catch { + components = new Component[](0); + } + } else { components = new Component[](0); } @@ -353,22 +391,29 @@ contract AdapterRegistry is Ownable, ProtocolManager, TokenAdapterManager { returns (TokenBalance memory) { TokenAdapter adapter = TokenAdapter(tokenAdapter[tokenType]); + TokenBalance memory tokenBalance; + tokenBalance.amount = amount; - try adapter.getMetadata(token) returns (TokenMetadata memory result) { - return TokenBalance({ - metadata: result, - amount: amount - }); - } catch { - return TokenBalance({ - metadata: TokenMetadata({ + if (address(adapter) != address(0)) { + try adapter.getMetadata(token) returns (TokenMetadata memory result) { + tokenBalance.metadata = result; + } catch { + tokenBalance.metadata = TokenMetadata({ token: token, name: "Not available", symbol: "N/A", - decimals: 18 - }), - amount: amount + decimals: 0 + }); + } + } else { + tokenBalance.metadata = TokenMetadata({ + token: token, + name: "Not available", + symbol: "N/A", + decimals: 0 }); } + + return tokenBalance; } } diff --git a/contracts/ERC20.sol b/contracts/ERC20.sol index 9348e87b..dbcf7c88 100755 --- a/contracts/ERC20.sol +++ b/contracts/ERC20.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; @@ -21,9 +21,9 @@ interface ERC20 { function approve(address, uint256) external returns (bool); function transfer(address, uint256) external returns (bool); function transferFrom(address, address, uint256) external returns (bool); - function balanceOf(address) external view returns (uint256); - function totalSupply() external view returns (uint256); - function decimals() external view returns (uint8); - function symbol() external view returns (string memory); function name() external view returns (string memory); + function symbol() external view returns (string memory); + function decimals() external view returns (uint8); + function totalSupply() external view returns (uint256); + function balanceOf(address) external view returns (uint256); } diff --git a/contracts/Ownable.sol b/contracts/Ownable.sol index 8b14502c..a5753340 100755 --- a/contracts/Ownable.sol +++ b/contracts/Ownable.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; diff --git a/contracts/ProtocolManager.sol b/contracts/ProtocolManager.sol index 4af85708..5f38fcb7 100755 --- a/contracts/ProtocolManager.sol +++ b/contracts/ProtocolManager.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { Ownable } from "./Ownable.sol"; @@ -204,20 +204,16 @@ abstract contract ProtocolManager is Ownable { { require(isValidProtocol(protocolName), "PM: bad name!"); require(index < protocolAdapters[protocolName].length, "PM: bad index!"); - require(newAdapterAddress != address(0) || newSupportedTokens.length != 0, "PM: empty!"); + require(newAdapterAddress != address(0), "PM: empty!"); address adapterAddress = protocolAdapters[protocolName][index]; - if (newAdapterAddress != address(0)) { + if (newAdapterAddress == adapterAddress) { + supportedTokens[adapterAddress] = newSupportedTokens; + } else { protocolAdapters[protocolName][index] = newAdapterAddress; - if (newSupportedTokens.length != 0) { - supportedTokens[newAdapterAddress] = newSupportedTokens; - } else { - supportedTokens[newAdapterAddress] = supportedTokens[adapterAddress]; - } + supportedTokens[newAdapterAddress] = newSupportedTokens; delete supportedTokens[adapterAddress]; - } else { - supportedTokens[adapterAddress] = newSupportedTokens; } protocolMetadata[protocolName].version++; @@ -337,7 +333,7 @@ abstract contract ProtocolManager is Ownable { description: metadata.description, websiteURL: metadata.websiteURL, iconURL: metadata.iconURL, - version: 0 + version: metadata.version }); for (uint256 i = 0; i < adapters.length; i++) { @@ -389,7 +385,7 @@ abstract contract ProtocolManager is Ownable { internal { require(adapter != address(0), "PM: zero!"); - require(tokens.length != 0, "PM: empty!"); + require(supportedTokens[adapter].length == 0, "PM: exists!"); protocolAdapters[protocolName].push(adapter); supportedTokens[adapter] = tokens; diff --git a/contracts/Strings.sol b/contracts/Strings.sol index 3e1438b0..d92bb1d0 100755 --- a/contracts/Strings.sol +++ b/contracts/Strings.sol @@ -13,9 +13,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; + /** * @notice Library for strings. * @author Igor Sobolev diff --git a/contracts/Structs.sol b/contracts/Structs.sol index 697cd60d..07c91a67 100755 --- a/contracts/Structs.sol +++ b/contracts/Structs.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; diff --git a/contracts/TokenAdapterManager.sol b/contracts/TokenAdapterManager.sol index a8e6e033..31eb8061 100755 --- a/contracts/TokenAdapterManager.sol +++ b/contracts/TokenAdapterManager.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { Ownable } from "./Ownable.sol"; diff --git a/contracts/adapters/ERC20TokenAdapter.sol b/contracts/adapters/ERC20TokenAdapter.sol index cf4a8a3c..7e5c5323 100755 --- a/contracts/adapters/ERC20TokenAdapter.sol +++ b/contracts/adapters/ERC20TokenAdapter.sol @@ -13,12 +13,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { TokenAdapter } from "./TokenAdapter.sol"; import { ERC20 } from "../ERC20.sol"; import { TokenMetadata, Component } from "../Structs.sol"; +import { TokenAdapter } from "./TokenAdapter.sol"; /** @@ -30,6 +30,7 @@ contract ERC20TokenAdapter is TokenAdapter { address internal constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address internal constant SAI = 0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359; + address internal constant CSAI = 0x45A2FDfED7F7a2c791fb1bdF6075b83faD821ddE; /** * @return TokenMetadata struct with ERC20-style token info. @@ -50,6 +51,13 @@ contract ERC20TokenAdapter is TokenAdapter { symbol: "SAI", decimals: uint8(18) }); + } else if (token == CSAI) { + return TokenMetadata({ + token: CSAI, + name: "Compound Sai", + symbol: "cSAI", + decimals: uint8(8) + }); } else { return TokenMetadata({ token: token, diff --git a/contracts/adapters/ProtocolAdapter.sol b/contracts/adapters/ProtocolAdapter.sol index 7bac5844..67aac07f 100755 --- a/contracts/adapters/ProtocolAdapter.sol +++ b/contracts/adapters/ProtocolAdapter.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; @@ -26,11 +26,13 @@ interface ProtocolAdapter { /** * @dev MUST return "Asset" or "Debt". + * SHOULD be implemented by the public constant state variable. */ function adapterType() external pure returns (string memory); /** * @dev MUST return token type (default is "ERC20"). + * SHOULD be implemented by the public constant state variable. */ function tokenType() external pure returns (string memory); diff --git a/contracts/adapters/TokenAdapter.sol b/contracts/adapters/TokenAdapter.sol index d71cc0fa..7f1813de 100755 --- a/contracts/adapters/TokenAdapter.sol +++ b/contracts/adapters/TokenAdapter.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { TokenMetadata, Component } from "../Structs.sol"; @@ -40,9 +40,9 @@ interface TokenAdapter { /** * @dev MUST return array of Component structs with underlying tokens rates for the given token. * struct Component { - * address token; // Address of token contract - * string tokenType; // Token type ("ERC20" by default) - * uint256 rate; // Price per share (1e18) + * address token; // Address of token contract + * string tokenType; // Token type ("ERC20" by default) + * uint256 rate; // Price per share (1e18) * } */ function getComponents(address token) external view returns (Component[] memory); diff --git a/contracts/adapters/aave/AaveAssetAdapter.sol b/contracts/adapters/aave/AaveAssetAdapter.sol index c68f9b1f..2de6e37e 100755 --- a/contracts/adapters/aave/AaveAssetAdapter.sol +++ b/contracts/adapters/aave/AaveAssetAdapter.sol @@ -13,11 +13,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { ProtocolAdapter } from "../ProtocolAdapter.sol"; import { ERC20 } from "../../ERC20.sol"; +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; /** @@ -27,21 +27,9 @@ import { ERC20 } from "../../ERC20.sol"; */ contract AaveAssetAdapter is ProtocolAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "AToken"; - } + string public constant override tokenType = "AToken"; /** * @return Amount of ATokens held by the given account. diff --git a/contracts/adapters/aave/AaveDebtAdapter.sol b/contracts/adapters/aave/AaveDebtAdapter.sol index c68a5b3f..9d05d80f 100755 --- a/contracts/adapters/aave/AaveDebtAdapter.sol +++ b/contracts/adapters/aave/AaveDebtAdapter.sol @@ -13,11 +13,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { ProtocolAdapter } from "../ProtocolAdapter.sol"; -import { ERC20 } from "../../ERC20.sol"; /** @@ -51,21 +50,9 @@ contract AaveDebtAdapter is ProtocolAdapter { address internal constant PROVIDER = 0x24a42fD28C976A61Df5D00D0599C34c4f90748c8; - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Debt"; - } + string public constant override adapterType = "Debt"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "ERC20"; - } + string public constant override tokenType = "ERC20"; /** * @return Amount of debt of the given account for the protocol. diff --git a/contracts/adapters/aave/AaveTokenAdapter.sol b/contracts/adapters/aave/AaveTokenAdapter.sol index 016781cd..bea7197a 100755 --- a/contracts/adapters/aave/AaveTokenAdapter.sol +++ b/contracts/adapters/aave/AaveTokenAdapter.sol @@ -13,12 +13,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { TokenAdapter } from "../TokenAdapter.sol"; -import { TokenMetadata, Component } from "../../Structs.sol"; import { ERC20 } from "../../ERC20.sol"; +import { TokenMetadata, Component } from "../../Structs.sol"; +import { TokenAdapter } from "../TokenAdapter.sol"; /** diff --git a/contracts/adapters/balancer/BalancerAdapter.sol b/contracts/adapters/balancer/BalancerAdapter.sol new file mode 100755 index 00000000..1f50c582 --- /dev/null +++ b/contracts/adapters/balancer/BalancerAdapter.sol @@ -0,0 +1,42 @@ +// Copyright (C) 2020 Zerion Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +pragma solidity 0.6.5; +pragma experimental ABIEncoderV2; + +import { ERC20 } from "../../ERC20.sol"; +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; + + +/** + * @title Adapter for Balancer protocol. + * @dev Implementation of ProtocolAdapter interface. + * @author Igor Sobolev + */ +contract BalancerAdapter is ProtocolAdapter { + + string public constant override adapterType = "Asset"; + + string public constant override tokenType = "Balancer pool token"; + + /** + * @return Amount of Balancer pool tokens held by the given account. + * @param token Address of the pool! + * @dev Implementation of ProtocolAdapter interface function. + */ + function getBalance(address token, address account) external view override returns (uint256) { + return ERC20(token).balanceOf(account); + } +} diff --git a/contracts/adapters/balancer/BalancerTokenAdapter.sol b/contracts/adapters/balancer/BalancerTokenAdapter.sol new file mode 100755 index 00000000..4de6a237 --- /dev/null +++ b/contracts/adapters/balancer/BalancerTokenAdapter.sol @@ -0,0 +1,169 @@ +// Copyright (C) 2020 Zerion Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +pragma solidity 0.6.5; +pragma experimental ABIEncoderV2; + +import { ERC20 } from "../../ERC20.sol"; +import { TokenMetadata, Component } from "../../Structs.sol"; +import { TokenAdapter } from "../TokenAdapter.sol"; + + +/** + * @dev BPool contract interface. + * Only the functions required for UniswapAdapter contract are added. + * The BPool contract is available here + * github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol. + */ +interface BPool { + function getFinalTokens() external view returns (address[] memory); + function getBalance(address) external view returns (uint256); + function getNormalizedWeight(address) external view returns (uint256); +} + + +/** + * @title Token adapter for Balancer pool tokens. + * @dev Implementation of TokenAdapter interface. + * @author Igor Sobolev + */ +contract BalancerTokenAdapter is TokenAdapter { + + + /** + * @return TokenMetadata struct with ERC20-style token info. + * @dev Implementation of TokenAdapter interface function. + */ + function getMetadata(address token) external view override returns (TokenMetadata memory) { + return TokenMetadata({ + token: token, + name: getPoolName(token), + symbol: ERC20(token).symbol(), + decimals: ERC20(token).decimals() + }); + } + + /** + * @return Array of Component structs with underlying tokens rates for the given asset. + * @dev Implementation of TokenAdapter interface function. + */ + function getComponents(address token) external view override returns (Component[] memory) { + address[] memory underlyingTokensAddresses; + try BPool(token).getFinalTokens() returns (address[] memory result) { + underlyingTokensAddresses = result; + } catch { + underlyingTokensAddresses = new address[](0); + } + + uint256 totalSupply = ERC20(token).totalSupply(); + + Component[] memory underlyingTokens = new Component[](underlyingTokensAddresses.length); + + for (uint256 i = 0; i < underlyingTokens.length; i++) { + address underlyingToken = underlyingTokensAddresses[i]; + underlyingTokens[i] = Component({ + token: underlyingToken, + tokenType: "ERC20", + rate: BPool(token).getBalance(underlyingToken) * 1e18 / totalSupply + }); + } + + return underlyingTokens; + } + + function getPoolName(address token) internal view returns (string memory) { + address[] memory underlyingTokensAddresses; + try BPool(token).getFinalTokens() returns (address[] memory result) { + underlyingTokensAddresses = result; + } catch { + return "Unknown pool"; + } + + string memory poolName = ""; + uint256 lastIndex = underlyingTokensAddresses.length - 1; + for (uint256 i = 0; i < underlyingTokensAddresses.length; i++) { + poolName = string(abi.encodePacked( + poolName, + getPoolElement(token, underlyingTokensAddresses[i]), + i == lastIndex ? " pool" : " + " + )); + } + return poolName; + } + + function getPoolElement(address pool, address token) internal view returns (string memory) { + return string(abi.encodePacked( + convertToString(BPool(pool).getNormalizedWeight(token) / 1e16), + "% ", + getSymbol(token) + )); + } + + function getSymbol(address token) internal view returns (string memory) { + (, bytes memory returnData) = token.staticcall( + abi.encodeWithSelector(ERC20(token).symbol.selector) + ); + + if (returnData.length == 32) { + return convertToString(abi.decode(returnData, (bytes32))); + } else { + return abi.decode(returnData, (string)); + } + } + + /** + * @dev Internal function to convert bytes32 to string and trim zeroes. + */ + function convertToString(bytes32 data) internal pure returns (string memory) { + uint256 length = 0; + bytes memory result; + + for (uint256 i = 0; i < 32; i++) { + if (data[i] != bytes1(0)) { + length++; + } + } + + result = new bytes(length); + + for (uint256 i = 0; i < length; i++) { + result[i] = data[i]; + } + + return string(result); + } + + /** + * @dev Internal function to convert uint256 to string and trim zeroes. + */ + function convertToString(uint256 data) internal pure returns (string memory) { + uint256 length = 0; + + uint256 dataCopy = data; + while (dataCopy != 0){ + length++; + dataCopy /= 10; + } + + bytes memory result = new bytes(length); + dataCopy = data; + for (uint256 i = length - 1; i < length; i--) { + result[i] = bytes1(uint8(48 + dataCopy % 10)); + dataCopy /= 10; + } + + return string(result); + } +} diff --git a/contracts/adapters/compound/CompoundAssetAdapter.sol b/contracts/adapters/compound/CompoundAssetAdapter.sol index 997e934e..964c7fca 100755 --- a/contracts/adapters/compound/CompoundAssetAdapter.sol +++ b/contracts/adapters/compound/CompoundAssetAdapter.sol @@ -13,11 +13,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { ProtocolAdapter } from "../ProtocolAdapter.sol"; import { ERC20 } from "../../ERC20.sol"; +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; /** @@ -27,21 +27,9 @@ import { ERC20 } from "../../ERC20.sol"; */ contract CompoundAssetAdapter is ProtocolAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "CToken"; - } + string public constant override tokenType = "CToken"; /** * @return Amount of CTokens held by the given account. diff --git a/contracts/adapters/compound/CompoundDebtAdapter.sol b/contracts/adapters/compound/CompoundDebtAdapter.sol index 0d902ab8..0a8899c1 100755 --- a/contracts/adapters/compound/CompoundDebtAdapter.sol +++ b/contracts/adapters/compound/CompoundDebtAdapter.sol @@ -13,11 +13,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { ProtocolAdapter } from "../ProtocolAdapter.sol"; import { ERC20 } from "../../ERC20.sol"; +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; /** @@ -50,21 +50,9 @@ contract CompoundDebtAdapter is ProtocolAdapter { address internal constant REGISTRY = 0xE6881a7d699d3A350Ce5bba0dbD59a9C36778Cb7; - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Debt"; - } + string public constant override adapterType = "Debt"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "ERC20"; - } + string public constant override tokenType = "ERC20"; /** * @return Amount of debt of the given account for the protocol. diff --git a/contracts/adapters/compound/CompoundRegistry.sol b/contracts/adapters/compound/CompoundRegistry.sol index 75e6bedd..93230d45 100755 --- a/contracts/adapters/compound/CompoundRegistry.sol +++ b/contracts/adapters/compound/CompoundRegistry.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; /** diff --git a/contracts/adapters/compound/CompoundTokenAdapter.sol b/contracts/adapters/compound/CompoundTokenAdapter.sol index f5461ecf..11ae9fb4 100755 --- a/contracts/adapters/compound/CompoundTokenAdapter.sol +++ b/contracts/adapters/compound/CompoundTokenAdapter.sol @@ -13,13 +13,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { TokenAdapter } from "../TokenAdapter.sol"; -import { CompoundRegistry } from "./CompoundRegistry.sol"; -import { TokenMetadata, Component } from "../../Structs.sol"; import { ERC20 } from "../../ERC20.sol"; +import { TokenMetadata, Component } from "../../Structs.sol"; +import { CompoundRegistry } from "./CompoundRegistry.sol"; +import { TokenAdapter } from "../TokenAdapter.sol"; /** @@ -43,18 +43,28 @@ contract CompoundTokenAdapter is TokenAdapter { address internal constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address internal constant CETH = 0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5; + address internal constant CSAI = 0xF5DCe57282A584D2746FaF1593d3121Fcac444dC; /** * @return TokenMetadata struct with ERC20-style token info. * @dev Implementation of TokenAdapter interface function. */ function getMetadata(address token) external view override returns (TokenMetadata memory) { - return TokenMetadata({ - token: token, - name: ERC20(token).name(), - symbol: ERC20(token).symbol(), - decimals: ERC20(token).decimals() - }); + if (token == CSAI) { + return TokenMetadata({ + token: CSAI, + name: "Compound Sai", + symbol: "cSAI", + decimals: uint8(8) + }); + } else { + return TokenMetadata({ + token: token, + name: ERC20(token).name(), + symbol: ERC20(token).symbol(), + decimals: ERC20(token).decimals() + }); + } } /** diff --git a/contracts/adapters/curve/CurveAdapter.sol b/contracts/adapters/curve/CurveAdapter.sol index ad3788de..d4be6d87 100755 --- a/contracts/adapters/curve/CurveAdapter.sol +++ b/contracts/adapters/curve/CurveAdapter.sol @@ -13,24 +13,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { ProtocolAdapter } from "../ProtocolAdapter.sol"; import { ERC20 } from "../../ERC20.sol"; - - -/** - * @dev stableswap contract interface. - * Only the functions required for CurveAdapter contract are added. - * The stableswap contract is available here - * github.com/curvefi/curve-contract/blob/compounded/vyper/stableswap.vy. - */ -// solhint-disable-next-line contract-name-camelcase -interface stableswap { - function coins(int128) external view returns (address); - function balances(int128) external view returns (uint256); -} +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; /** @@ -40,21 +27,9 @@ interface stableswap { */ contract CurveAdapter is ProtocolAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "Curve pool token"; - } + string public constant override tokenType = "Curve pool token"; /** * @return Amount of Curve pool tokens held by the given account. diff --git a/contracts/adapters/curve/CurveTokenAdapter.sol b/contracts/adapters/curve/CurveTokenAdapter.sol index 53e5ec34..e82c9f31 100755 --- a/contracts/adapters/curve/CurveTokenAdapter.sol +++ b/contracts/adapters/curve/CurveTokenAdapter.sol @@ -13,12 +13,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { TokenAdapter } from "../TokenAdapter.sol"; -import { TokenMetadata, Component } from "../../Structs.sol"; import { ERC20 } from "../../ERC20.sol"; +import { TokenMetadata, Component } from "../../Structs.sol"; +import { TokenAdapter } from "../TokenAdapter.sol"; /** diff --git a/contracts/adapters/dydx/DyDxAdapter.sol b/contracts/adapters/dydx/DyDxAdapter.sol index 92c925fb..d6cd6d20 100755 --- a/contracts/adapters/dydx/DyDxAdapter.sol +++ b/contracts/adapters/dydx/DyDxAdapter.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; diff --git a/contracts/adapters/dydx/DyDxAssetAdapter.sol b/contracts/adapters/dydx/DyDxAssetAdapter.sol index 5cb25cd9..42cec3c8 100755 --- a/contracts/adapters/dydx/DyDxAssetAdapter.sol +++ b/contracts/adapters/dydx/DyDxAssetAdapter.sol @@ -13,11 +13,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { ProtocolAdapter } from "../ProtocolAdapter.sol"; import { DyDxAdapter } from "./DyDxAdapter.sol"; +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; /** @@ -60,21 +60,9 @@ interface SoloMargin { */ contract DyDxAssetAdapter is ProtocolAdapter, DyDxAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "ERC20"; - } + string public constant override tokenType = "ERC20"; /** * @return Amount of tokens held by the given account. diff --git a/contracts/adapters/dydx/DyDxDebtAdapter.sol b/contracts/adapters/dydx/DyDxDebtAdapter.sol index 230e4939..fa1bfd89 100755 --- a/contracts/adapters/dydx/DyDxDebtAdapter.sol +++ b/contracts/adapters/dydx/DyDxDebtAdapter.sol @@ -13,11 +13,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { ProtocolAdapter } from "../ProtocolAdapter.sol"; import { DyDxAdapter } from "./DyDxAdapter.sol"; +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; /** @@ -60,21 +60,9 @@ interface SoloMargin { */ contract DyDxDebtAdapter is ProtocolAdapter, DyDxAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Debt"; - } + string public constant override adapterType = "Debt"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "ERC20"; - } + string public constant override tokenType = "ERC20"; /** * @return Amount of tokens held by the given account. diff --git a/contracts/adapters/idle/IdleAdapter.sol b/contracts/adapters/idle/IdleAdapter.sol index a7763b77..62bce4a9 100644 --- a/contracts/adapters/idle/IdleAdapter.sol +++ b/contracts/adapters/idle/IdleAdapter.sol @@ -13,11 +13,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { ProtocolAdapter } from "../ProtocolAdapter.sol"; import { ERC20 } from "../../ERC20.sol"; +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; /** @@ -27,21 +27,9 @@ import { ERC20 } from "../../ERC20.sol"; */ contract IdleAdapter is ProtocolAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "IdleToken"; - } + string public constant override tokenType = "IdleToken"; /** * @return Amount of IdleTokens held by the given account. diff --git a/contracts/adapters/idle/IdleTokenAdapter.sol b/contracts/adapters/idle/IdleTokenAdapter.sol index 949013f5..06741b95 100644 --- a/contracts/adapters/idle/IdleTokenAdapter.sol +++ b/contracts/adapters/idle/IdleTokenAdapter.sol @@ -13,12 +13,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { TokenAdapter } from "../TokenAdapter.sol"; -import { TokenMetadata, Component } from "../../Structs.sol"; import { ERC20 } from "../../ERC20.sol"; +import { TokenMetadata, Component } from "../../Structs.sol"; +import { TokenAdapter } from "../TokenAdapter.sol"; /** diff --git a/contracts/adapters/iearn/IearnAdapter.sol b/contracts/adapters/iearn/IearnAdapter.sol index 7f6d6393..25c7a199 100755 --- a/contracts/adapters/iearn/IearnAdapter.sol +++ b/contracts/adapters/iearn/IearnAdapter.sol @@ -13,11 +13,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { ProtocolAdapter } from "../ProtocolAdapter.sol"; import { ERC20 } from "../../ERC20.sol"; +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; /** @@ -27,21 +27,9 @@ import { ERC20 } from "../../ERC20.sol"; */ contract IearnAdapter is ProtocolAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "YToken"; - } + string public constant override tokenType = "YToken"; /** * @return Amount of YTokens held by the given account. diff --git a/contracts/adapters/iearn/IearnTokenAdapter.sol b/contracts/adapters/iearn/IearnTokenAdapter.sol index 2aa5b757..e5937927 100755 --- a/contracts/adapters/iearn/IearnTokenAdapter.sol +++ b/contracts/adapters/iearn/IearnTokenAdapter.sol @@ -13,12 +13,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { TokenAdapter } from "../TokenAdapter.sol"; -import { TokenMetadata, Component } from "../../Structs.sol"; import { ERC20 } from "../../ERC20.sol"; +import { TokenMetadata, Component } from "../../Structs.sol"; +import { TokenAdapter } from "../TokenAdapter.sol"; /** diff --git a/contracts/adapters/maker/ChaiAdapter.sol b/contracts/adapters/maker/ChaiAdapter.sol index dade210a..6805fde8 100755 --- a/contracts/adapters/maker/ChaiAdapter.sol +++ b/contracts/adapters/maker/ChaiAdapter.sol @@ -13,11 +13,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { ProtocolAdapter } from "../ProtocolAdapter.sol"; import { ERC20 } from "../../ERC20.sol"; +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; /** @@ -27,21 +27,9 @@ import { ERC20 } from "../../ERC20.sol"; */ contract ChaiAdapter is ProtocolAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "Chai token"; - } + string public constant override tokenType = "Chai token"; /** * @return Amount of Chai tokens held by the given account. diff --git a/contracts/adapters/maker/ChaiTokenAdapter.sol b/contracts/adapters/maker/ChaiTokenAdapter.sol index 55987b3c..02b18299 100755 --- a/contracts/adapters/maker/ChaiTokenAdapter.sol +++ b/contracts/adapters/maker/ChaiTokenAdapter.sol @@ -13,13 +13,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; +import { ERC20 } from "../../ERC20.sol"; +import { TokenMetadata, Component } from "../../Structs.sol"; import { TokenAdapter } from "../TokenAdapter.sol"; import { MKRAdapter } from "./MKRAdapter.sol"; -import { TokenMetadata, Component } from "../../Structs.sol"; -import { ERC20 } from "../../ERC20.sol"; /** diff --git a/contracts/adapters/maker/DSRAdapter.sol b/contracts/adapters/maker/DSRAdapter.sol index 69dc5836..ccc32c24 100755 --- a/contracts/adapters/maker/DSRAdapter.sol +++ b/contracts/adapters/maker/DSRAdapter.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { ProtocolAdapter } from "../ProtocolAdapter.sol"; @@ -41,21 +41,9 @@ interface Pot { */ contract DSRAdapter is ProtocolAdapter, MKRAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "ERC20"; - } + string public constant override tokenType = "ERC20"; /** * @return Amount of DAI locked on the protocol by the given account. diff --git a/contracts/adapters/maker/MCDAssetAdapter.sol b/contracts/adapters/maker/MCDAssetAdapter.sol index f2d0105c..5cb4752f 100755 --- a/contracts/adapters/maker/MCDAssetAdapter.sol +++ b/contracts/adapters/maker/MCDAssetAdapter.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { ProtocolAdapter } from "../ProtocolAdapter.sol"; @@ -65,21 +65,9 @@ interface DssCdpManager { */ contract MCDAssetAdapter is ProtocolAdapter, MKRAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "ERC20"; - } + string public constant override tokenType = "ERC20"; /** * @return Amount of collateral locked on the protocol by the given account. diff --git a/contracts/adapters/maker/MCDDebtAdapter.sol b/contracts/adapters/maker/MCDDebtAdapter.sol index 79a42ed5..0a0219eb 100755 --- a/contracts/adapters/maker/MCDDebtAdapter.sol +++ b/contracts/adapters/maker/MCDDebtAdapter.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { ProtocolAdapter } from "../ProtocolAdapter.sol"; @@ -65,21 +65,9 @@ interface DssCdpManager { */ contract MCDDebtAdapter is ProtocolAdapter, MKRAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Debt"; - } + string public constant override adapterType = "Debt"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "ERC20"; - } + string public constant override tokenType = "ERC20"; /** * @return Amount of debt of the given account for the protocol. diff --git a/contracts/adapters/maker/MKRAdapter.sol b/contracts/adapters/maker/MKRAdapter.sol index de07dd52..176a46cb 100755 --- a/contracts/adapters/maker/MKRAdapter.sol +++ b/contracts/adapters/maker/MKRAdapter.sol @@ -13,13 +13,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; /** * @title Maker adapter abstract contract. - * @dev Base contract for MCD, DSR, and (later) Chai adapters. + * @dev Base contract for MCD, DSR, and Chai adapters. + * Math function are taken from the Pot contract available here + * github.com/makerdao/dss/blob/master/src/pot.sol. * @author Igor Sobolev */ abstract contract MKRAdapter { diff --git a/contracts/adapters/poolTogether/PoolTogetherAdapter.sol b/contracts/adapters/poolTogether/PoolTogetherAdapter.sol index d708cc36..93827d59 100755 --- a/contracts/adapters/poolTogether/PoolTogetherAdapter.sol +++ b/contracts/adapters/poolTogether/PoolTogetherAdapter.sol @@ -13,11 +13,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { ProtocolAdapter } from "../ProtocolAdapter.sol"; -import { ERC20 } from "../../ERC20.sol"; /** @@ -38,21 +37,9 @@ interface BasePool { */ contract PoolTogetherAdapter is ProtocolAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "PoolTogether pool"; - } + string public constant override tokenType = "PoolTogether pool"; /** * @return Amount of tokens locked in the pool by the given account. diff --git a/contracts/adapters/poolTogether/PoolTogetherTokenAdapter.sol b/contracts/adapters/poolTogether/PoolTogetherTokenAdapter.sol index e43fab5f..dda7dffe 100755 --- a/contracts/adapters/poolTogether/PoolTogetherTokenAdapter.sol +++ b/contracts/adapters/poolTogether/PoolTogetherTokenAdapter.sol @@ -13,12 +13,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { TokenAdapter } from "../TokenAdapter.sol"; -import { TokenMetadata, Component } from "../../Structs.sol"; import { ERC20 } from "../../ERC20.sol"; +import { TokenMetadata, Component } from "../../Structs.sol"; +import { TokenAdapter } from "../TokenAdapter.sol"; /** diff --git a/contracts/adapters/synthetix/SynthetixAssetAdapter.sol b/contracts/adapters/synthetix/SynthetixAssetAdapter.sol index 0cb5135c..7192fd78 100755 --- a/contracts/adapters/synthetix/SynthetixAssetAdapter.sol +++ b/contracts/adapters/synthetix/SynthetixAssetAdapter.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { ProtocolAdapter } from "../ProtocolAdapter.sol"; @@ -49,21 +49,9 @@ interface Synthetix { */ contract SynthetixAssetAdapter is ProtocolAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "ERC20"; - } + string public constant override tokenType = "ERC20"; /** * @return Amount of SNX locked on the protocol by the given account. diff --git a/contracts/adapters/synthetix/SynthetixDebtAdapter.sol b/contracts/adapters/synthetix/SynthetixDebtAdapter.sol index 08f08ee5..1d871b84 100755 --- a/contracts/adapters/synthetix/SynthetixDebtAdapter.sol +++ b/contracts/adapters/synthetix/SynthetixDebtAdapter.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { ProtocolAdapter } from "../ProtocolAdapter.sol"; @@ -50,21 +50,9 @@ contract SynthetixDebtAdapter is ProtocolAdapter { address internal constant SNX = 0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F; - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Debt"; - } + string public constant override adapterType = "Debt"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "ERC20"; - } + string public constant override tokenType = "ERC20"; /** * @return Amount of debt of the given account for the protocol. diff --git a/contracts/adapters/uniswap/UniswapV1Adapter.sol b/contracts/adapters/uniswap/UniswapV1Adapter.sol index d580af30..0993b91b 100755 --- a/contracts/adapters/uniswap/UniswapV1Adapter.sol +++ b/contracts/adapters/uniswap/UniswapV1Adapter.sol @@ -13,22 +13,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { ProtocolAdapter } from "../ProtocolAdapter.sol"; import { ERC20 } from "../../ERC20.sol"; - - -/** - * @dev Factory contract interface. - * Only the functions required for UniswapAdapter contract are added. - * The Factory contract is available here - * github.com/Uniswap/contracts-vyper/blob/master/contracts/uniswap_factory.vy. - */ -interface Factory { - function getToken(address) external view returns (address); -} +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; /** @@ -38,21 +27,9 @@ interface Factory { */ contract UniswapV1Adapter is ProtocolAdapter { - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "Uniswap V1 pool token"; - } + string public constant override tokenType = "Uniswap V1 pool token"; /** * @return Amount of Uniswap pool tokens held by the given account. diff --git a/contracts/adapters/uniswap/UniswapV1TokenAdapter.sol b/contracts/adapters/uniswap/UniswapV1TokenAdapter.sol index 433b9011..7ae9e8f4 100755 --- a/contracts/adapters/uniswap/UniswapV1TokenAdapter.sol +++ b/contracts/adapters/uniswap/UniswapV1TokenAdapter.sol @@ -13,12 +13,23 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { TokenAdapter } from "../TokenAdapter.sol"; -import { TokenMetadata, Component } from "../../Structs.sol"; import { ERC20 } from "../../ERC20.sol"; +import { TokenMetadata, Component } from "../../Structs.sol"; +import { TokenAdapter } from "../TokenAdapter.sol"; + + +/** + * @dev CToken contract interface. + * Only the functions required for UniswapV1TokenAdapter contract are added. + * The CToken contract is available here + * github.com/compound-finance/compound-protocol/blob/master/contracts/CToken.sol. + */ +interface CToken { + function isCToken() external view returns (bool); +} /** @@ -55,6 +66,7 @@ contract UniswapV1TokenAdapter is TokenAdapter { address internal constant FACTORY = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95; address internal constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address internal constant SAI_POOL = 0x09cabEC1eAd1c0Ba254B09efb3EE13841712bE14; + address internal constant CSAI_POOL = 0x45A2FDfED7F7a2c791fb1bdF6075b83faD821ddE; /** * @return TokenMetadata struct with ERC20-style token info. @@ -85,7 +97,11 @@ contract UniswapV1TokenAdapter is TokenAdapter { rate: token.balance * 1e18 / totalSupply }); - underlyingTokenType = "ERC20"; + try CToken(underlyingToken).isCToken() returns (bool) { + underlyingTokenType = "CToken"; + } catch { + underlyingTokenType = "ERC20"; + } underlyingTokens[1] = Component({ token: underlyingToken, @@ -99,6 +115,8 @@ contract UniswapV1TokenAdapter is TokenAdapter { function getPoolName(address token) internal view returns (string memory) { if (token == SAI_POOL) { return "SAI pool"; + } else if (token == CSAI_POOL) { + return "cSAI pool"; } else { return string(abi.encodePacked(getSymbol(Factory(FACTORY).getToken(token)), " pool")); } @@ -117,7 +135,7 @@ contract UniswapV1TokenAdapter is TokenAdapter { } /** - * @dev Internal function to convert bytes32 to string. + * @dev Internal function to convert bytes32 to string and trim zeroes. */ function convertToString(bytes32 data) internal pure returns (string memory) { uint256 length = 0; diff --git a/contracts/adapters/zrx/ZrxAdapter.sol b/contracts/adapters/zrx/ZrxAdapter.sol index a2bd92fc..7641c967 100755 --- a/contracts/adapters/zrx/ZrxAdapter.sol +++ b/contracts/adapters/zrx/ZrxAdapter.sol @@ -13,11 +13,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; -import { ProtocolAdapter } from "../ProtocolAdapter.sol"; import { ERC20 } from "../../ERC20.sol"; +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; /** @@ -38,23 +38,11 @@ interface Staking { */ contract ZrxAdapter is ProtocolAdapter { - address internal constant STAKING = 0xa26e80e7Dea86279c6d778D702Cc413E6CFfA777; + string public constant override adapterType = "Asset"; - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override tokenType = "ERC20"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "ERC20"; - } + address internal constant STAKING = 0xa26e80e7Dea86279c6d778D702Cc413E6CFfA777; /** * @return Amount of ZRX locked on the protocol by the given account. diff --git a/contracts/interactiveAdapters/InteractiveAdapter.sol b/contracts/interactiveAdapters/InteractiveAdapter.sol index a3d1e949..9539e11b 100755 --- a/contracts/interactiveAdapters/InteractiveAdapter.sol +++ b/contracts/interactiveAdapters/InteractiveAdapter.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { ProtocolAdapter } from "../adapters/ProtocolAdapter.sol"; diff --git a/contracts/mock/MockAdapter.sol b/contracts/mock/MockAdapter.sol index 58493995..c02c4810 100755 --- a/contracts/mock/MockAdapter.sol +++ b/contracts/mock/MockAdapter.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { ProtocolAdapter } from "../adapters/ProtocolAdapter.sol"; @@ -31,21 +31,9 @@ contract MockAdapter is ProtocolAdapter { balanceOf[msg.sender] = 1000; } - /** - * @return Type of the adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function adapterType() external pure override returns (string memory) { - return "Asset"; - } + string public constant override adapterType = "Asset"; - /** - * @return Type of the token used in adapter. - * @dev Implementation of ProtocolAdapter interface function. - */ - function tokenType() external pure override returns (string memory) { - return "ERC20"; - } + string public constant override tokenType = "ERC20"; /** * @return Mock balance. diff --git a/contracts/mock/MockTokenAdapter.sol b/contracts/mock/MockTokenAdapter.sol index 93db0f14..e8c6280a 100755 --- a/contracts/mock/MockTokenAdapter.sol +++ b/contracts/mock/MockTokenAdapter.sol @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity 0.6.4; +pragma solidity 0.6.5; pragma experimental ABIEncoderV2; import { TokenMetadata, Component } from "../Structs.sol"; diff --git a/migrations_scripts/1_deploy_registry_and_add_adapters.js b/migrations_scripts/1_deploy_registry_and_add_adapters.js index 98b3635a..f62a8afd 100755 --- a/migrations_scripts/1_deploy_registry_and_add_adapters.js +++ b/migrations_scripts/1_deploy_registry_and_add_adapters.js @@ -1,10 +1,12 @@ const AaveAssetAdapter = artifacts.require('AaveAssetAdapter'); const AaveDebtAdapter = artifacts.require('AaveDebtAdapter'); +const BalancerAdapter = artifacts.require('BalancerAdapter'); const CompoundAssetAdapter = artifacts.require('CompoundAssetAdapter'); const CompoundDebtAdapter = artifacts.require('CompoundDebtAdapter'); const CurveAdapter = artifacts.require('CurveAdapter'); const DyDxAssetAdapter = artifacts.require('DyDxAssetAdapter'); const DyDxDebtAdapter = artifacts.require('DyDxDebtAdapter'); +const IdleAdapter = artifacts.require('IdleAdapter'); const IearnAdapter = artifacts.require('IearnAdapter'); const ChaiAdapter = artifacts.require('ChaiAdapter'); const DSRAdapter = artifacts.require('DSRAdapter'); @@ -17,19 +19,40 @@ const UniswapV1Adapter = artifacts.require('UniswapV1Adapter'); const ZrxAdapter = artifacts.require('ZrxAdapter'); const ERC20TokenAdapter = artifacts.require('ERC20TokenAdapter'); const AaveTokenAdapter = artifacts.require('AaveTokenAdapter'); +const BalancerTokenAdapter = artifacts.require('BalancerTokenAdapter'); const CompoundTokenAdapter = artifacts.require('CompoundTokenAdapter'); const CurveTokenAdapter = artifacts.require('CurveTokenAdapter'); +const IdleTokenAdapter = artifacts.require('IdleTokenAdapter'); const IearnTokenAdapter = artifacts.require('IearnTokenAdapter'); const ChaiTokenAdapter = artifacts.require('ChaiTokenAdapter'); const PoolTogetherTokenAdapter = artifacts.require('PoolTogetherTokenAdapter'); const UniswapV1TokenAdapter = artifacts.require('UniswapV1TokenAdapter'); const AdapterRegistry = artifacts.require('AdapterRegistry'); +const aDaiAddress = '0xfC1E690f61EFd961294b3e1Ce3313fBD8aa4f85d'; +const aTusdAddress = '0x4DA9b813057D04BAef4e5800E36083717b4a0341'; +const aUsdcAddress = '0x9bA00D6856a4eDF4665BcA2C2309936572473B7E'; +const aUsdtAddress = '0x71fc860F7D3A592A4a98740e39dB31d25db65ae8'; +const aSusdAddress = '0x625aE63000f46200499120B906716420bd059240'; +const aBusdAddress = '0x6Ee0f7BB50a54AB5253dA0667B0Dc2ee526C30a8'; +const aLendAddress = '0x7D2D3688Df45Ce7C552E19c27e007673da9204B8'; +const aBatAddress = '0xE1BA0FB44CCb0D11b80F92f4f8Ed94CA3fF51D00'; +const aEthAddress = '0x3a3A65aAb0dd2A17E3F1947bA16138cd37d08c04'; +const aLinkAddress = '0xA64BD6C70Cb9051F6A9ba1F163Fdc07E0DfB5F84'; +const aKncAddress = '0x9D91BE44C06d373a8a226E1f3b146956083803eB'; +const aRepAddress = '0x71010A9D003445aC60C4e6A7017c1E89A477B438'; +const aMkrAddress = '0x7deB5e830be29F91E298ba5FF1356BB7f8146998'; +const aManaAddress = '0x6FCE4A401B6B80ACe52baAefE4421Bd188e76F6f'; +const aZrxAddress = '0x6Fb0855c404E09c47C3fBCA25f08d4E41f9F062f'; +const aSnxAddress = '0x328C4c80BC7aCa0834Db37e6600A6c49E12Da4DE'; +const aWbtcAddress = '0xFC4B8ED459e00e5400be803A9BB3954234FD50e3'; + const daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; const tusdAddress = '0x0000000000085d4780B73119b644AE5ecd22b376'; const usdcAddress = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'; const usdtAddress = '0xdAC17F958D2ee523a2206206994597C13D831ec7'; const susdAddress = '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51'; +const busdAddress = '0x4Fabb145d64652a948d72533023f6E7A623C7C53'; const lendAddress = '0x80fB784B7eD66730e8b1DBd9820aFD29931aab03'; const batAddress = '0x0D8775F648430679A709E98d2b0Cb6250d2887EF'; const ethAddress = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'; @@ -65,6 +88,8 @@ const yUSDCv3 = '0x26EA744E5B887E5205727f55dFBE8685e3b21951'; const yUSDTv3 = '0xE6354ed5bC4b393a5Aad09f21c46E101e692d447'; const yBUSDv3 = '0x04bC0Ab673d88aE9dbC9DA2380cB6B79C4BCa9aE'; +const idleDAI = '0x10eC0D497824e342bCB0EDcE00959142aAa766dD'; +const idleUSDC = '0xeB66ACc3d011056B00ea521F8203580C2E5d3991'; const ssCompoundTokenAddress = '0x845838DF265Dcd2c412A1Dc9e959c7d08537f8a2'; const ssYTokenAddress = '0xdF5e0e81Dff6FAF3A7e52BA697820c5e32D806A8'; @@ -78,12 +103,32 @@ const usdcPoolAddress = '0x0034Ea9808E620A0EF79261c51AF20614B742B24'; const chaiAddress = '0x06AF07097C9Eeb7fD685c692751D5C66dB49c215'; -const aaveAdapterTokens = [ +const aaveAssetAdapterTokens = [ + aDaiAddress, + aTusdAddress, + aUsdcAddress, + aUsdtAddress, + aSusdAddress, + aBusdAddress, + aLendAddress, + aBatAddress, + aEthAddress, + aLinkAddress, + aKncAddress, + aRepAddress, + aMkrAddress, + aManaAddress, + aZrxAddress, + aSnxAddress, + aWbtcAddress, +]; +const aaveDebtAdapterTokens = [ daiAddress, tusdAddress, usdcAddress, usdtAddress, susdAddress, + busdAddress, lendAddress, batAddress, ethAddress, @@ -127,6 +172,10 @@ const dydxAdapterTokens = [ usdcAddress, daiAddress, ]; +const idleAdapterTokens = [ + idleDAI, + idleUSDC, +]; const iearn2AdapterTokens = [ yDAIv2, yUSDCv2, @@ -165,57 +214,26 @@ const synthetixAssetAdapterTokens = [ const synthetixDebtAdapterTokens = [ susdAddress, ]; -const uniswapV1AdapterTokens = [ // top 30 pools - '0x5e74c9036fb86bd7ecdcb084a0673efc32ea31cb', - '0x2b591e99afe9f32eaa6214f7b7629768c40eeb39', - '0x6b175474e89094c44da98b954eedeac495271d0f', - '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2', - '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - '0xc011a72400e58ecd99ee497cf89e3775d4bd732f', - '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - '0x0d8775f648430679a709e98d2b0cb6250d2887ef', - '0x514910771af9ca656af840dff83e8264ecf986ca', - '0xdd974d5c2e2928dea5f71b9825b8b646686bd200', - '0xcf8f9555d55ce45a3a33a81d6ef99a2a2e71dee2', - '0x57ab1ec28d129707052df4df418d58a2d46d5f51', - '0x93ed3fbe21207ec2e8f2d3c3de6e058cb73bc04d', - '0x960b236a07cf122663c4303350609a66a7b288c0', - '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', - '0x9cb2f26a23b8d89973f08c957c4d7cdf75cd341c', - '0xb4efd85c19999d84251304bda99e90b92300bd93', - '0xbbbbca6a901c926f240b89eacb641d8aec7aeafd', - '0xaaaf91d9b90df800df4f55c205fd6989c977e73a', - '0xb4272071ecadd69d933adcd19ca99fe80664fc08', - '0x3212b29e33587a00fb1c83346f5dbfa69a458923', - '0x1985365e9f78359a9b6ad760e32412f4a445e862', - '0xe41d2489571d322189246dafa5ebde1f4699f498', - '0x42d6622dece394b54999fbd73d108123806f6a18', - '0xe0b7927c4af23765cb51314a0e0521a9645f0e2a', - '0x4946fcea7c692606e8908002e55a582af44ac121', - '0x408e41876cccdc0f92210600ef50372656052a38', - '0x6810e776880c02933d47db1b9fc05908e5386b96', -]; const zrxAdapterTokens = [ zrxAddress, ]; let protocolNames = []; let metadata = []; -let adapters = [[], [], [], [], [], [], [], [], [], [], [], [], []]; -let tokens = [[], [], [], [], [], [], [], [], [], [], [], [], []]; +let adapters = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], []]; +let tokens = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], []]; let tokenAdapters = []; module.exports = async (deployer, network, accounts) => { await deployer.deploy(AaveAssetAdapter, { from: accounts[0] }) .then(() => { adapters[0].push(AaveAssetAdapter.address); - tokens[0].push(aaveAdapterTokens); + tokens[0].push(aaveAssetAdapterTokens); }); await deployer.deploy(AaveDebtAdapter, { from: accounts[0] }) .then(() => { adapters[0].push(AaveDebtAdapter.address); - tokens[0].push(aaveAdapterTokens); + tokens[0].push(aaveDebtAdapterTokens); }); protocolNames.push('Aave'); metadata.push([ @@ -225,15 +243,28 @@ module.exports = async (deployer, network, accounts) => { 'protocol-icons.s3.amazonaws.com/aave.png', '0', ]); + await deployer.deploy(BalancerAdapter, { from: accounts[0] }) + .then(() => { + adapters[1].push(BalancerAdapter.address); + tokens[1].push([]); + }); + protocolNames.push('Balancer'); + metadata.push([ + 'Balancer', + 'Non-custodial portfolio manager, liquidity provider, and price sensor', + 'pools.balancer.exchange', + 'protocol-icons.s3.amazonaws.com/balancer.png', + '0', + ]); await deployer.deploy(CompoundAssetAdapter, { from: accounts[0] }) .then(() => { - adapters[1].push(CompoundAssetAdapter.address); - tokens[1].push(compoundAssetAdapterTokens); + adapters[2].push(CompoundAssetAdapter.address); + tokens[2].push(compoundAssetAdapterTokens); }); await deployer.deploy(CompoundDebtAdapter, { from: accounts[0] }) .then(() => { - adapters[1].push(CompoundDebtAdapter.address); - tokens[1].push(compoundDebtAdapterTokens); + adapters[2].push(CompoundDebtAdapter.address); + tokens[2].push(compoundDebtAdapterTokens); }); protocolNames.push('Compound'); metadata.push([ @@ -245,8 +276,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(CurveAdapter, { from: accounts[0] }) .then(() => { - adapters[2].push(CurveAdapter.address); - tokens[2].push(curveAdapterTokens); + adapters[3].push(CurveAdapter.address); + tokens[3].push(curveAdapterTokens); }); protocolNames.push('Curve'); metadata.push([ @@ -258,13 +289,13 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(DyDxAssetAdapter, { from: accounts[0] }) .then(() => { - adapters[3].push(DyDxAssetAdapter.address); - tokens[3].push(dydxAdapterTokens); + adapters[4].push(DyDxAssetAdapter.address); + tokens[4].push(dydxAdapterTokens); }); await deployer.deploy(DyDxDebtAdapter, { from: accounts[0] }) .then(() => { - adapters[3].push(DyDxDebtAdapter.address); - tokens[3].push(dydxAdapterTokens); + adapters[4].push(DyDxDebtAdapter.address); + tokens[4].push(dydxAdapterTokens); }); protocolNames.push('dYdX'); metadata.push([ @@ -274,10 +305,23 @@ module.exports = async (deployer, network, accounts) => { 'protocol-icons.s3.amazonaws.com/dYdX.png', '0', ]); + await deployer.deploy(IdleAdapter, { from: accounts[0] }) + .then(() => { + adapters[5].push(IdleAdapter.address); + tokens[5].push(idleAdapterTokens); + }); + protocolNames.push('Idle'); + metadata.push([ + 'Idle', + 'Yield aggregator for lending platforms', + 'idle.finance', + 'protocol-icons.s3.amazonaws.com/idle.png', + '0', + ]); await deployer.deploy(IearnAdapter, { from: accounts[0] }) .then(() => { - adapters[4].push(IearnAdapter.address); - tokens[4].push(iearn2AdapterTokens); + adapters[6].push(IearnAdapter.address); + tokens[6].push(iearn2AdapterTokens); }); protocolNames.push('iearn.finance (v2)'); metadata.push([ @@ -289,8 +333,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(IearnAdapter, { from: accounts[0] }) .then(() => { - adapters[5].push(IearnAdapter.address); - tokens[5].push(iearn3AdapterTokens); + adapters[7].push(IearnAdapter.address); + tokens[7].push(iearn3AdapterTokens); }); protocolNames.push('iearn.finance (v3)'); metadata.push([ @@ -302,8 +346,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(ChaiAdapter, { from: accounts[0] }) .then(() => { - adapters[6].push(ChaiAdapter.address); - tokens[6].push(chaiAdapterTokens); + adapters[8].push(ChaiAdapter.address); + tokens[8].push(chaiAdapterTokens); }); protocolNames.push('Chai'); metadata.push([ @@ -315,8 +359,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(DSRAdapter, { from: accounts[0] }) .then(() => { - adapters[7].push(DSRAdapter.address); - tokens[7].push(dsrAdapterTokens); + adapters[9].push(DSRAdapter.address); + tokens[9].push(dsrAdapterTokens); }); protocolNames.push('Dai Savings Rate'); metadata.push([ @@ -328,13 +372,13 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(MCDAssetAdapter, { from: accounts[0] }) .then(() => { - adapters[8].push(MCDAssetAdapter.address); - tokens[8].push(mcdAssetAdapterTokens); + adapters[10].push(MCDAssetAdapter.address); + tokens[10].push(mcdAssetAdapterTokens); }); await deployer.deploy(MCDDebtAdapter, { from: accounts[0] }) .then(() => { - adapters[8].push(MCDDebtAdapter.address); - tokens[8].push(mcdDebtAdapterTokens); + adapters[10].push(MCDDebtAdapter.address); + tokens[10].push(mcdDebtAdapterTokens); }); protocolNames.push('Multi-Collateral Dai'); metadata.push([ @@ -346,8 +390,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(PoolTogetherAdapter, { from: accounts[0] }) .then(() => { - adapters[9].push(PoolTogetherAdapter.address); - tokens[9].push(poolTogetherAdapterTokens); + adapters[11].push(PoolTogetherAdapter.address); + tokens[11].push(poolTogetherAdapterTokens); }); protocolNames.push('PoolTogether'); metadata.push([ @@ -359,13 +403,13 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(SynthetixAssetAdapter, { from: accounts[0] }) .then(() => { - adapters[10].push(SynthetixAssetAdapter.address); - tokens[10].push(synthetixAssetAdapterTokens); + adapters[12].push(SynthetixAssetAdapter.address); + tokens[12].push(synthetixAssetAdapterTokens); }); await deployer.deploy(SynthetixDebtAdapter, { from: accounts[0] }) .then(() => { - adapters[10].push(SynthetixDebtAdapter.address); - tokens[10].push(synthetixDebtAdapterTokens); + adapters[12].push(SynthetixDebtAdapter.address); + tokens[12].push(synthetixDebtAdapterTokens); }); protocolNames.push('Synthetix'); metadata.push([ @@ -377,8 +421,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(UniswapV1Adapter, { from: accounts[0] }) .then(() => { - adapters[11].push(UniswapV1Adapter.address); - tokens[11].push(uniswapV1AdapterTokens); + adapters[13].push(UniswapV1Adapter.address); + tokens[13].push([]); }); protocolNames.push('Uniswap V1'); metadata.push([ @@ -390,8 +434,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(ZrxAdapter, { from: accounts[0] }) .then(() => { - adapters[12].push(ZrxAdapter.address); - tokens[12].push(zrxAdapterTokens); + adapters[14].push(ZrxAdapter.address); + tokens[14].push(zrxAdapterTokens); }); protocolNames.push('0x Staking'); metadata.push([ @@ -401,6 +445,7 @@ module.exports = async (deployer, network, accounts) => { 'protocol-icons.s3.amazonaws.com/0x-staking.png', '0', ]); + await deployer.deploy(ERC20TokenAdapter, { from: accounts[0] }) .then(() => { tokenAdapters.push( @@ -413,6 +458,12 @@ module.exports = async (deployer, network, accounts) => { AaveTokenAdapter.address, ); }); + await deployer.deploy(BalancerTokenAdapter, { from: accounts[0] }) + .then(() => { + tokenAdapters.push( + BalancerTokenAdapter.address, + ); + }); await deployer.deploy(CompoundTokenAdapter, { from: accounts[0] }) .then(() => { tokenAdapters.push( @@ -425,6 +476,12 @@ module.exports = async (deployer, network, accounts) => { CurveTokenAdapter.address, ); }); + await deployer.deploy(IdleTokenAdapter, { from: accounts[0] }) + .then(() => { + tokenAdapters.push( + IdleTokenAdapter.address, + ); + }); await deployer.deploy(IearnTokenAdapter, { from: accounts[0] }) .then(() => { tokenAdapters.push( @@ -465,8 +522,10 @@ module.exports = async (deployer, network, accounts) => { [ 'ERC20', 'AToken', + 'Balancer pool token', 'CToken', 'Curve pool token', + 'IdleToken', 'YToken', 'Chai token', 'PoolTogether pool', diff --git a/migrations_scripts/1_use_registry_and_add_adapters.js b/migrations_scripts/1_use_registry_and_add_adapters.js index 48cf137f..e02c440d 100755 --- a/migrations_scripts/1_use_registry_and_add_adapters.js +++ b/migrations_scripts/1_use_registry_and_add_adapters.js @@ -1,10 +1,12 @@ const AaveAssetAdapter = artifacts.require('AaveAssetAdapter'); const AaveDebtAdapter = artifacts.require('AaveDebtAdapter'); +const BalancerAdapter = artifacts.require('BalancerAdapter'); const CompoundAssetAdapter = artifacts.require('CompoundAssetAdapter'); const CompoundDebtAdapter = artifacts.require('CompoundDebtAdapter'); const CurveAdapter = artifacts.require('CurveAdapter'); const DyDxAssetAdapter = artifacts.require('DyDxAssetAdapter'); const DyDxDebtAdapter = artifacts.require('DyDxDebtAdapter'); +const IdleAdapter = artifacts.require('IdleAdapter'); const IearnAdapter = artifacts.require('IearnAdapter'); const ChaiAdapter = artifacts.require('ChaiAdapter'); const DSRAdapter = artifacts.require('DSRAdapter'); @@ -17,19 +19,40 @@ const UniswapV1Adapter = artifacts.require('UniswapV1Adapter'); const ZrxAdapter = artifacts.require('ZrxAdapter'); const ERC20TokenAdapter = artifacts.require('ERC20TokenAdapter'); const AaveTokenAdapter = artifacts.require('AaveTokenAdapter'); +const BalancerTokenAdapter = artifacts.require('BalancerTokenAdapter'); const CompoundTokenAdapter = artifacts.require('CompoundTokenAdapter'); const CurveTokenAdapter = artifacts.require('CurveTokenAdapter'); +const IdleTokenAdapter = artifacts.require('IdleTokenAdapter'); const IearnTokenAdapter = artifacts.require('IearnTokenAdapter'); const ChaiTokenAdapter = artifacts.require('ChaiTokenAdapter'); const PoolTogetherTokenAdapter = artifacts.require('PoolTogetherTokenAdapter'); const UniswapV1TokenAdapter = artifacts.require('UniswapV1TokenAdapter'); const AdapterRegistry = artifacts.require('AdapterRegistry'); +const aDaiAddress = '0xfC1E690f61EFd961294b3e1Ce3313fBD8aa4f85d'; +const aTusdAddress = '0x4DA9b813057D04BAef4e5800E36083717b4a0341'; +const aUsdcAddress = '0x9bA00D6856a4eDF4665BcA2C2309936572473B7E'; +const aUsdtAddress = '0x71fc860F7D3A592A4a98740e39dB31d25db65ae8'; +const aSusdAddress = '0x625aE63000f46200499120B906716420bd059240'; +const aBusdAddress = '0x6Ee0f7BB50a54AB5253dA0667B0Dc2ee526C30a8'; +const aLendAddress = '0x7D2D3688Df45Ce7C552E19c27e007673da9204B8'; +const aBatAddress = '0xE1BA0FB44CCb0D11b80F92f4f8Ed94CA3fF51D00'; +const aEthAddress = '0x3a3A65aAb0dd2A17E3F1947bA16138cd37d08c04'; +const aLinkAddress = '0xA64BD6C70Cb9051F6A9ba1F163Fdc07E0DfB5F84'; +const aKncAddress = '0x9D91BE44C06d373a8a226E1f3b146956083803eB'; +const aRepAddress = '0x71010A9D003445aC60C4e6A7017c1E89A477B438'; +const aMkrAddress = '0x7deB5e830be29F91E298ba5FF1356BB7f8146998'; +const aManaAddress = '0x6FCE4A401B6B80ACe52baAefE4421Bd188e76F6f'; +const aZrxAddress = '0x6Fb0855c404E09c47C3fBCA25f08d4E41f9F062f'; +const aSnxAddress = '0x328C4c80BC7aCa0834Db37e6600A6c49E12Da4DE'; +const aWbtcAddress = '0xFC4B8ED459e00e5400be803A9BB3954234FD50e3'; + const daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; const tusdAddress = '0x0000000000085d4780B73119b644AE5ecd22b376'; const usdcAddress = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'; const usdtAddress = '0xdAC17F958D2ee523a2206206994597C13D831ec7'; const susdAddress = '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51'; +const busdAddress = '0x4Fabb145d64652a948d72533023f6E7A623C7C53'; const lendAddress = '0x80fB784B7eD66730e8b1DBd9820aFD29931aab03'; const batAddress = '0x0D8775F648430679A709E98d2b0Cb6250d2887EF'; const ethAddress = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'; @@ -80,12 +103,32 @@ const usdcPoolAddress = '0x0034Ea9808E620A0EF79261c51AF20614B742B24'; const chaiAddress = '0x06AF07097C9Eeb7fD685c692751D5C66dB49c215'; -const aaveAdapterTokens = [ +const aaveAssetAdapterTokens = [ + aDaiAddress, + aTusdAddress, + aUsdcAddress, + aUsdtAddress, + aSusdAddress, + aBusdAddress, + aLendAddress, + aBatAddress, + aEthAddress, + aLinkAddress, + aKncAddress, + aRepAddress, + aMkrAddress, + aManaAddress, + aZrxAddress, + aSnxAddress, + aWbtcAddress, +]; +const aaveDebtAdapterTokens = [ daiAddress, tusdAddress, usdcAddress, usdtAddress, susdAddress, + busdAddress, lendAddress, batAddress, ethAddress, @@ -129,6 +172,10 @@ const dydxAdapterTokens = [ usdcAddress, daiAddress, ]; +const idleAdapterTokens = [ + idleDAI, + idleUSDC, +]; const iearn2AdapterTokens = [ yDAIv2, yUSDCv2, @@ -143,10 +190,6 @@ const iearn3AdapterTokens = [ yUSDTv3, yBUSDv3, ]; -const idleAdapterTokens = [ - idleDAI, - idleUSDC -]; const dsrAdapterTokens = [ daiAddress, ]; @@ -171,57 +214,26 @@ const synthetixAssetAdapterTokens = [ const synthetixDebtAdapterTokens = [ susdAddress, ]; -const uniswapV1AdapterTokens = [ // top 50 pools - '0x5e74c9036fb86bd7ecdcb084a0673efc32ea31cb', - '0x2b591e99afe9f32eaa6214f7b7629768c40eeb39', - '0x6b175474e89094c44da98b954eedeac495271d0f', - '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2', - '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - '0xc011a72400e58ecd99ee497cf89e3775d4bd732f', - '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', - '0x0d8775f648430679a709e98d2b0cb6250d2887ef', - '0x514910771af9ca656af840dff83e8264ecf986ca', - '0xdd974d5c2e2928dea5f71b9825b8b646686bd200', - '0xcf8f9555d55ce45a3a33a81d6ef99a2a2e71dee2', - '0x57ab1ec28d129707052df4df418d58a2d46d5f51', - '0x93ed3fbe21207ec2e8f2d3c3de6e058cb73bc04d', - '0x960b236a07cf122663c4303350609a66a7b288c0', - '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359', - '0x9cb2f26a23b8d89973f08c957c4d7cdf75cd341c', - // '0xb4efd85c19999d84251304bda99e90b92300bd93', - // '0xbbbbca6a901c926f240b89eacb641d8aec7aeafd', - // '0xaaaf91d9b90df800df4f55c205fd6989c977e73a', - // '0xb4272071ecadd69d933adcd19ca99fe80664fc08', - // '0x3212b29e33587a00fb1c83346f5dbfa69a458923', - // '0x1985365e9f78359a9b6ad760e32412f4a445e862', - // '0xe41d2489571d322189246dafa5ebde1f4699f498', - // '0x42d6622dece394b54999fbd73d108123806f6a18', - // '0xe0b7927c4af23765cb51314a0e0521a9645f0e2a', - // '0x4946fcea7c692606e8908002e55a582af44ac121', - // '0x408e41876cccdc0f92210600ef50372656052a38', - // '0x6810e776880c02933d47db1b9fc05908e5386b96', -]; const zrxAdapterTokens = [ zrxAddress, ]; let protocolNames = []; let metadata = []; -let adapters = [[], [], [], [], [], [], [], [], [], [], [], [], [], []]; -let tokens = [[], [], [], [], [], [], [], [], [], [], [], [], [], []]; +let adapters = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], []]; +let tokens = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], []]; let tokenAdapters = []; module.exports = async (deployer, network, accounts) => { await deployer.deploy(AaveAssetAdapter, { from: accounts[0] }) .then(() => { adapters[0].push(AaveAssetAdapter.address); - tokens[0].push(aaveAdapterTokens); + tokens[0].push(aaveAssetAdapterTokens); }); await deployer.deploy(AaveDebtAdapter, { from: accounts[0] }) .then(() => { adapters[0].push(AaveDebtAdapter.address); - tokens[0].push(aaveAdapterTokens); + tokens[0].push(aaveDebtAdapterTokens); }); protocolNames.push('Aave'); metadata.push([ @@ -231,15 +243,28 @@ module.exports = async (deployer, network, accounts) => { 'protocol-icons.s3.amazonaws.com/aave.png', '0', ]); + await deployer.deploy(BalancerAdapter, { from: accounts[0] }) + .then(() => { + adapters[1].push(BalancerAdapter.address); + tokens[1].push([]); + }); + protocolNames.push('Balancer'); + metadata.push([ + 'Balancer', + 'Non-custodial portfolio manager, liquidity provider, and price sensor', + 'pools.balancer.exchange', + 'protocol-icons.s3.amazonaws.com/balancer.png', + '0', + ]); await deployer.deploy(CompoundAssetAdapter, { from: accounts[0] }) .then(() => { - adapters[1].push(CompoundAssetAdapter.address); - tokens[1].push(compoundAssetAdapterTokens); + adapters[2].push(CompoundAssetAdapter.address); + tokens[2].push(compoundAssetAdapterTokens); }); await deployer.deploy(CompoundDebtAdapter, { from: accounts[0] }) .then(() => { - adapters[1].push(CompoundDebtAdapter.address); - tokens[1].push(compoundDebtAdapterTokens); + adapters[2].push(CompoundDebtAdapter.address); + tokens[2].push(compoundDebtAdapterTokens); }); protocolNames.push('Compound'); metadata.push([ @@ -251,8 +276,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(CurveAdapter, { from: accounts[0] }) .then(() => { - adapters[2].push(CurveAdapter.address); - tokens[2].push(curveAdapterTokens); + adapters[3].push(CurveAdapter.address); + tokens[3].push(curveAdapterTokens); }); protocolNames.push('Curve'); metadata.push([ @@ -264,13 +289,13 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(DyDxAssetAdapter, { from: accounts[0] }) .then(() => { - adapters[3].push(DyDxAssetAdapter.address); - tokens[3].push(dydxAdapterTokens); + adapters[4].push(DyDxAssetAdapter.address); + tokens[4].push(dydxAdapterTokens); }); await deployer.deploy(DyDxDebtAdapter, { from: accounts[0] }) .then(() => { - adapters[3].push(DyDxDebtAdapter.address); - tokens[3].push(dydxAdapterTokens); + adapters[4].push(DyDxDebtAdapter.address); + tokens[4].push(dydxAdapterTokens); }); protocolNames.push('dYdX'); metadata.push([ @@ -282,8 +307,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(IdleAdapter, { from: accounts[0] }) .then(() => { - adapters[4].push(IdleAdapter.address); - tokens[4].push(idleAdapterTokens); + adapters[5].push(IdleAdapter.address); + tokens[5].push(idleAdapterTokens); }); protocolNames.push('Idle'); metadata.push([ @@ -295,8 +320,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(IearnAdapter, { from: accounts[0] }) .then(() => { - adapters[5].push(IearnAdapter.address); - tokens[5].push(iearn2AdapterTokens); + adapters[6].push(IearnAdapter.address); + tokens[6].push(iearn2AdapterTokens); }); protocolNames.push('iearn.finance (v2)'); metadata.push([ @@ -308,8 +333,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(IearnAdapter, { from: accounts[0] }) .then(() => { - adapters[6].push(IearnAdapter.address); - tokens[6].push(iearn3AdapterTokens); + adapters[7].push(IearnAdapter.address); + tokens[7].push(iearn3AdapterTokens); }); protocolNames.push('iearn.finance (v3)'); metadata.push([ @@ -321,8 +346,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(ChaiAdapter, { from: accounts[0] }) .then(() => { - adapters[7].push(ChaiAdapter.address); - tokens[7].push(chaiAdapterTokens); + adapters[8].push(ChaiAdapter.address); + tokens[8].push(chaiAdapterTokens); }); protocolNames.push('Chai'); metadata.push([ @@ -334,8 +359,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(DSRAdapter, { from: accounts[0] }) .then(() => { - adapters[8].push(DSRAdapter.address); - tokens[8].push(dsrAdapterTokens); + adapters[9].push(DSRAdapter.address); + tokens[9].push(dsrAdapterTokens); }); protocolNames.push('Dai Savings Rate'); metadata.push([ @@ -347,13 +372,13 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(MCDAssetAdapter, { from: accounts[0] }) .then(() => { - adapters[9].push(MCDAssetAdapter.address); - tokens[9].push(mcdAssetAdapterTokens); + adapters[10].push(MCDAssetAdapter.address); + tokens[10].push(mcdAssetAdapterTokens); }); await deployer.deploy(MCDDebtAdapter, { from: accounts[0] }) .then(() => { - adapters[9].push(MCDDebtAdapter.address); - tokens[9].push(mcdDebtAdapterTokens); + adapters[10].push(MCDDebtAdapter.address); + tokens[10].push(mcdDebtAdapterTokens); }); protocolNames.push('Multi-Collateral Dai'); metadata.push([ @@ -365,8 +390,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(PoolTogetherAdapter, { from: accounts[0] }) .then(() => { - adapters[10].push(PoolTogetherAdapter.address); - tokens[10].push(poolTogetherAdapterTokens); + adapters[11].push(PoolTogetherAdapter.address); + tokens[11].push(poolTogetherAdapterTokens); }); protocolNames.push('PoolTogether'); metadata.push([ @@ -378,13 +403,13 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(SynthetixAssetAdapter, { from: accounts[0] }) .then(() => { - adapters[11].push(SynthetixAssetAdapter.address); - tokens[11].push(synthetixAssetAdapterTokens); + adapters[12].push(SynthetixAssetAdapter.address); + tokens[12].push(synthetixAssetAdapterTokens); }); await deployer.deploy(SynthetixDebtAdapter, { from: accounts[0] }) .then(() => { - adapters[11].push(SynthetixDebtAdapter.address); - tokens[11].push(synthetixDebtAdapterTokens); + adapters[12].push(SynthetixDebtAdapter.address); + tokens[12].push(synthetixDebtAdapterTokens); }); protocolNames.push('Synthetix'); metadata.push([ @@ -396,8 +421,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(UniswapV1Adapter, { from: accounts[0] }) .then(() => { - adapters[12].push(UniswapV1Adapter.address); - tokens[12].push(uniswapV1AdapterTokens); + adapters[13].push(UniswapV1Adapter.address); + tokens[13].push([]); }); protocolNames.push('Uniswap V1'); metadata.push([ @@ -409,8 +434,8 @@ module.exports = async (deployer, network, accounts) => { ]); await deployer.deploy(ZrxAdapter, { from: accounts[0] }) .then(() => { - adapters[13].push(ZrxAdapter.address); - tokens[13].push(zrxAdapterTokens); + adapters[14].push(ZrxAdapter.address); + tokens[14].push(zrxAdapterTokens); }); protocolNames.push('0x Staking'); metadata.push([ @@ -433,6 +458,12 @@ module.exports = async (deployer, network, accounts) => { AaveTokenAdapter.address, ); }); + await deployer.deploy(BalancerTokenAdapter, { from: accounts[0] }) + .then(() => { + tokenAdapters.push( + BalancerTokenAdapter.address, + ); + }); await deployer.deploy(CompoundTokenAdapter, { from: accounts[0] }) .then(() => { tokenAdapters.push( @@ -445,16 +476,16 @@ module.exports = async (deployer, network, accounts) => { CurveTokenAdapter.address, ); }); - await deployer.deploy(IearnTokenAdapter, { from: accounts[0] }) + await deployer.deploy(IdleTokenAdapter, { from: accounts[0] }) .then(() => { tokenAdapters.push( - IearnTokenAdapter.address, + IdleTokenAdapter.address, ); }); - await deployer.deploy(IdleTokenAdapter, { from: accounts[0] }) + await deployer.deploy(IearnTokenAdapter, { from: accounts[0] }) .then(() => { tokenAdapters.push( - IdleTokenAdapter.address, + IearnTokenAdapter.address, ); }); await deployer.deploy(ChaiTokenAdapter, { from: accounts[0] }) @@ -491,6 +522,7 @@ module.exports = async (deployer, network, accounts) => { [ 'ERC20', 'AToken', + 'Balancer pool token', 'CToken', 'Curve pool token', 'IdleToken', diff --git a/test/AaveAssetAdapter.js b/test/AaveAssetAdapter.js index da840c88..799c3c5d 100755 --- a/test/AaveAssetAdapter.js +++ b/test/AaveAssetAdapter.js @@ -11,7 +11,6 @@ contract('AaveAssetAdapter', () => { const aBATAddress = '0xE1BA0FB44CCb0D11b80F92f4f8Ed94CA3fF51D00'; const daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; const batAddress = '0x0D8775F648430679A709E98d2b0Cb6250d2887EF'; - const kncAddress = '0xdd974D5C2e2928deA5F71b9825b8b646686BD200'; const testAddress = '0x42b9dF65B219B3dD36FF330A4dD8f327A6Ada990'; let accounts; @@ -25,12 +24,6 @@ contract('AaveAssetAdapter', () => { 'DAI', '18', ]; - const knc = [ - kncAddress, - 'Kyber Network Crystal', - 'KNC', - '18', - ]; const bat = [ batAddress, 'Basic Attention Token', @@ -94,10 +87,8 @@ contract('AaveAssetAdapter', () => { .then((result) => { displayToken(result[0].adapterBalances[0].balances[0].underlying[0]); displayToken(result[0].adapterBalances[0].balances[1].underlying[0]); - displayToken(result[0].adapterBalances[0].balances[2].underlying[0]); assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[0].metadata, dai); - assert.deepEqual(result[0].adapterBalances[0].balances[1].underlying[0].metadata, knc); - assert.deepEqual(result[0].adapterBalances[0].balances[2].underlying[0].metadata, bat); + assert.deepEqual(result[0].adapterBalances[0].balances[1].underlying[0].metadata, bat); }); }); }); diff --git a/test/AaveDebtAdapter.js b/test/AaveDebtAdapter.js index 89593a2f..8a3146ee 100755 --- a/test/AaveDebtAdapter.js +++ b/test/AaveDebtAdapter.js @@ -27,22 +27,16 @@ contract('AaveDebtAdapter', () => { let adapterRegistry; let protocolAdapterAddress; let erc20TokenAdapterAddress; - const dai = [ - daiAddress, - 'Dai Stablecoin', - 'DAI', - '18', - ]; const knc = [ kncAddress, 'Kyber Network Crystal', 'KNC', '18', ]; - const bat = [ - batAddress, - 'Basic Attention Token', - 'BAT', + const mkr = [ + mkrAddress, + 'Maker', + 'MKR', '18', ]; @@ -111,10 +105,8 @@ contract('AaveDebtAdapter', () => { .then((result) => { displayToken(result[0].adapterBalances[0].balances[0].base); displayToken(result[0].adapterBalances[0].balances[1].base); - displayToken(result[0].adapterBalances[0].balances[2].base); - assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, dai); - assert.deepEqual(result[0].adapterBalances[0].balances[1].base.metadata, knc); - assert.deepEqual(result[0].adapterBalances[0].balances[2].base.metadata, bat); + assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, knc); + assert.deepEqual(result[0].adapterBalances[0].balances[1].base.metadata, mkr); }); }); }); diff --git a/test/AdapterRegistry.js b/test/AdapterRegistry.js index ee5743e9..91755b5e 100755 --- a/test/AdapterRegistry.js +++ b/test/AdapterRegistry.js @@ -364,27 +364,27 @@ contract('AdapterRegistry', () => { })); }); - it('should not add protocol with no assets', async () => { - await expectRevert(adapterRegistry.methods.addProtocols( - ['Mock2'], - [[ - 'Mock Protocol Name', - 'Mock protocol description', - 'Mock website', - 'Mock icon', - '0', - ]], - - [[ - protocolAdapterAddress, - ]], - [[[]]], - ) - .send({ - from: accounts[0], - gas: '300000', - })); - }); + // it('should not add protocol with no assets', async () => { + // await expectRevert(adapterRegistry.methods.addProtocols( + // ['Mock2'], + // [[ + // 'Mock Protocol Name', + // 'Mock protocol description', + // 'Mock website', + // 'Mock icon', + // '0', + // ]], + // + // [[ + // protocolAdapterAddress, + // ]], + // [[[]]], + // ) + // .send({ + // from: accounts[0], + // gas: '300000', + // })); + // }); it('should add protocol by the owner', async () => { await adapterRegistry.methods.addProtocols( @@ -397,7 +397,7 @@ contract('AdapterRegistry', () => { '0', ]], [[ - protocolAdapterAddress, + ONE, ]], [[[ protocolAdapterAddress, @@ -488,7 +488,7 @@ contract('AdapterRegistry', () => { '0', ]], [[ - protocolAdapterAddress, + ONE, ]], [[[ protocolAdapterAddress, @@ -528,7 +528,7 @@ contract('AdapterRegistry', () => { '0', ]], [[ - protocolAdapterAddress, + TWO, ]], [[[ protocolAdapterAddress, @@ -682,11 +682,11 @@ contract('AdapterRegistry', () => { })); }); - it('should not add protocol adapter with no adapters', async () => { + it('should not add protocol adapter that is already in use', async () => { await expectRevert(adapterRegistry.methods.addProtocolAdapters( 'Mock', - [], - [[]], + [protocolAdapterAddress], + [[protocolAdapterAddress]], ) .send({ from: accounts[0], @@ -694,11 +694,11 @@ contract('AdapterRegistry', () => { })); }); - it('should not add protocol adapter with zero address', async () => { + it('should not add protocol adapter with no adapters', async () => { await expectRevert(adapterRegistry.methods.addProtocolAdapters( 'Mock', - [ZERO], - [[protocolAdapterAddress]], + [], + [[]], ) .send({ from: accounts[0], @@ -706,11 +706,11 @@ contract('AdapterRegistry', () => { })); }); - it('should not add protocol adapter without tokens', async () => { + it('should not add protocol adapter with zero address', async () => { await expectRevert(adapterRegistry.methods.addProtocolAdapters( 'Mock', - [protocolAdapterAddress], - [[]], + [ZERO], + [[protocolAdapterAddress]], ) .send({ from: accounts[0], @@ -718,10 +718,22 @@ contract('AdapterRegistry', () => { })); }); + // it('should not add protocol adapter without tokens', async () => { + // await expectRevert(adapterRegistry.methods.addProtocolAdapters( + // 'Mock', + // [protocolAdapterAddress], + // [[]], + // ) + // .send({ + // from: accounts[0], + // gas: '300000', + // })); + // }); + it('should add protocol adapter by the owner', async () => { await adapterRegistry.methods.addProtocolAdapters( 'Mock', - [protocolAdapterAddress], + [ONE], [[protocolAdapterAddress]], ) .send({ @@ -731,7 +743,7 @@ contract('AdapterRegistry', () => { await adapterRegistry.methods.getProtocolAdapters('Mock') .call() .then((result) => { - assert.deepEqual(result, [protocolAdapterAddress, protocolAdapterAddress]); + assert.deepEqual(result, [protocolAdapterAddress, ONE]); }); }); @@ -900,12 +912,12 @@ contract('AdapterRegistry', () => { })); }); - it('should not update protocol adapter with empty input', async () => { + it('should not update protocol adapter with zero address', async () => { await expectRevert(adapterRegistry.methods.updateProtocolAdapter( 'Mock', 0, ZERO, - [], + [ONE], ) .send({ from: accounts[0], @@ -913,6 +925,19 @@ contract('AdapterRegistry', () => { })); }); + // it('should not update protocol adapter with same address', async () => { + // await expectRevert(adapterRegistry.methods.updateProtocolAdapter( + // 'Mock', + // 0, + // protocolAdapterAddress, + // [ONE], + // ) + // .send({ + // from: accounts[0], + // gas: '300000', + // })); + // }); + it('should update protocol adapter by the owner', async () => { await adapterRegistry.methods.updateProtocolAdapter( 'Mock', @@ -932,7 +957,7 @@ contract('AdapterRegistry', () => { await adapterRegistry.methods.updateProtocolAdapter( 'Mock', 0, - ZERO, + ONE, [ONE, ONE], ) .send({ @@ -969,6 +994,21 @@ contract('AdapterRegistry', () => { .then((result) => { assert.deepEqual(result, [TWO, TWO]); }); + await adapterRegistry.methods.updateProtocolAdapter( + 'Mock', + 0, + TWO, + [], + ) + .send({ + from: accounts[0], + gas: '300000', + }); + await adapterRegistry.methods.getSupportedTokens(TWO) + .call() + .then((result) => { + assert.deepEqual(result, []); + }); }); it('should not add token adapter not by the owner', async () => { @@ -1279,15 +1319,7 @@ contract('AdapterRegistry', () => { await adapterRegistry.methods.getBalances(accounts[1]) .call() .then((result) => { - assert.equal(result[0].metadata.name, 'Mock Protocol Name'); - assert.equal(result[0].metadata.description, 'Mock protocol description'); - assert.equal(result[0].metadata.websiteURL, 'Mock website'); - assert.equal(result[0].metadata.iconURL, 'Mock icon'); - assert.equal(result[0].metadata.version, '0'); - assert.equal(result[0].adapterBalances[0].metadata.adapterType, 'Asset'); - assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, mockAsset); - assert.equal(result[0].adapterBalances[0].balances[0].base.amount, 0); - assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying, []); + assert.equal(result.length, 0); }); }); }); diff --git a/test/AdapterRegistryDeployed.js b/test/AdapterRegistryDeployed.js index e56edb80..b826dce8 100755 --- a/test/AdapterRegistryDeployed.js +++ b/test/AdapterRegistryDeployed.js @@ -43,8 +43,8 @@ contract.skip('AdapterRegistry deployed', () => { 'Uniswap V1 pool token', 'PoolTogether pool', 'Chai token', - 'IdleToken', 'YToken', + 'IdleToken', 'Curve pool token', 'CToken', 'AToken', @@ -52,5 +52,9 @@ contract.skip('AdapterRegistry deployed', () => { ], ); }); + await adapterRegistry.methods.getBalances('0x42b9dF65B219B3dD36FF330A4dD8f327A6Ada990') + .estimateGas() + // eslint-disable-next-line no-console + .then((estimatedGas) => console.log(`Estimated gas for getBalances() call is ${estimatedGas}`)); }); }); diff --git a/test/BalancerAdapter.js b/test/BalancerAdapter.js new file mode 100755 index 00000000..b551d26b --- /dev/null +++ b/test/BalancerAdapter.js @@ -0,0 +1,119 @@ +import displayToken from './helpers/displayToken'; + +const AdapterRegistry = artifacts.require('./AdapterRegistry'); +const ProtocolAdapter = artifacts.require('./BalancerAdapter'); +const TokenAdapter = artifacts.require('./BalancerTokenAdapter'); +const ERC20TokenAdapter = artifacts.require('./ERC20TokenAdapter'); + +contract('BalancerAdapter', () => { + const wethDai3070PoolAddress = '0x53b89CE35928dda346c574D9105A5479CB87231c'; + const wethMkr2575PoolAddress = '0x987D7Cc04652710b74Fff380403f5c02f82e290a'; + const daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; + const mkrAddress = '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2'; + const wethAddress = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'; + const testAddress = '0x42b9dF65B219B3dD36FF330A4dD8f327A6Ada990'; + + let accounts; + let adapterRegistry; + let protocolAdapterAddress; + let tokenAdapterAddress; + let erc20TokenAdapterAddress; + const wethDai3070Pool = [ + wethDai3070PoolAddress, + '30% WETH + 70% DAI pool', + 'BPT', + '18', + ]; + const wethMkr2575Pool = [ + wethMkr2575PoolAddress, + '75% MKR + 25% WETH pool', + 'BPT', + '18', + ]; + const mkr = [ + mkrAddress, + 'Maker', + 'MKR', + '18', + ]; + const dai = [ + daiAddress, + 'Dai Stablecoin', + 'DAI', + '18', + ]; + const weth = [ + wethAddress, + 'Wrapped Ether', + 'WETH', + '18', + ]; + + beforeEach(async () => { + accounts = await web3.eth.getAccounts(); + await ProtocolAdapter.new({ from: accounts[0] }) + .then((result) => { + protocolAdapterAddress = result.address; + }); + await TokenAdapter.new({ from: accounts[0] }) + .then((result) => { + tokenAdapterAddress = result.address; + }); + await ERC20TokenAdapter.new({ from: accounts[0] }) + .then((result) => { + erc20TokenAdapterAddress = result.address; + }); + await AdapterRegistry.new({ from: accounts[0] }) + .then((result) => { + adapterRegistry = result.contract; + }); + await adapterRegistry.methods.addProtocols( + ['Balancer'], + [[ + 'Mock Protocol Name', + 'Mock protocol description', + 'Mock website', + 'Mock icon', + '0', + ]], + [[ + protocolAdapterAddress, + ]], + [[[ + wethDai3070PoolAddress, + wethMkr2575PoolAddress, + ]]], + ) + .send({ + from: accounts[0], + gas: '1000000', + }); + await adapterRegistry.methods.addTokenAdapters( + ['ERC20', 'Balancer pool token'], + [erc20TokenAdapterAddress, tokenAdapterAddress], + ) + .send({ + from: accounts[0], + gas: '1000000', + }); + }); + + it('should return correct balances', async () => { + await adapterRegistry.methods['getBalances(address)'](testAddress) + .call() + .then((result) => { + displayToken(result[0].adapterBalances[0].balances[0].underlying[0]); + displayToken(result[0].adapterBalances[0].balances[0].underlying[1]); + displayToken(result[0].adapterBalances[0].balances[0].base); + assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, wethDai3070Pool); + assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[0].metadata, weth); + assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[1].metadata, dai); + displayToken(result[0].adapterBalances[0].balances[1].underlying[0]); + displayToken(result[0].adapterBalances[0].balances[1].underlying[1]); + displayToken(result[0].adapterBalances[0].balances[1].base); + assert.deepEqual(result[0].adapterBalances[0].balances[1].base.metadata, wethMkr2575Pool); + assert.deepEqual(result[0].adapterBalances[0].balances[1].underlying[0].metadata, mkr); + assert.deepEqual(result[0].adapterBalances[0].balances[1].underlying[1].metadata, weth); + }); + }); +}); diff --git a/test/CompoundAssetAdapter.js b/test/CompoundAssetAdapter.js index 0e689871..f1100e80 100755 --- a/test/CompoundAssetAdapter.js +++ b/test/CompoundAssetAdapter.js @@ -102,11 +102,11 @@ contract('CompoundAssetAdapter', () => { await adapterRegistry.methods['getBalances(address)'](testAddress) .call() .then((result) => { - displayToken(result[0].adapterBalances[0].balances[6].underlying[0]); - displayToken(result[0].adapterBalances[0].balances[7].underlying[0]); + displayToken(result[0].adapterBalances[0].balances[4].underlying[0]); + displayToken(result[0].adapterBalances[0].balances[5].underlying[0]); assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[0].metadata, dai); - assert.deepEqual(result[0].adapterBalances[0].balances[4].underlying[0].metadata, sai); - assert.deepEqual(result[0].adapterBalances[0].balances[6].underlying[0].metadata, usdc); + assert.deepEqual(result[0].adapterBalances[0].balances[3].underlying[0].metadata, sai); + assert.deepEqual(result[0].adapterBalances[0].balances[4].underlying[0].metadata, usdc); }); }); }); diff --git a/test/CompoundDebtAdapter.js b/test/CompoundDebtAdapter.js index 3c7fba3c..32a0e068 100755 --- a/test/CompoundDebtAdapter.js +++ b/test/CompoundDebtAdapter.js @@ -25,13 +25,6 @@ contract('CompoundDebtAdapter', () => { 'DAI', '18', ]; - const sai = [ - saiAddress, - 'Sai Stablecoin v1.0', - 'SAI', - '18', - ]; - const usdc = [ usdcAddress, 'USD//C', @@ -98,8 +91,7 @@ contract('CompoundDebtAdapter', () => { displayToken(result[0].adapterBalances[0].balances[1].base); displayToken(result[0].adapterBalances[0].balances[3].base); assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, dai); - assert.deepEqual(result[0].adapterBalances[0].balances[4].base.metadata, sai); - assert.deepEqual(result[0].adapterBalances[0].balances[6].base.metadata, usdc); + assert.deepEqual(result[0].adapterBalances[0].balances[3].base.metadata, usdc); }); }); }); diff --git a/test/CurveAdapter.js b/test/CurveAdapter.js index e6c439fe..3f800db6 100755 --- a/test/CurveAdapter.js +++ b/test/CurveAdapter.js @@ -28,12 +28,6 @@ contract('CurveAdapter', () => { let erc20TokenAdapterAddress; let cTokenAdapterAddress; let yTokenAdapterAddress; - const ssUSDT = [ - ssUSDTTokenAddress, - 'cDAI+cUSDC+USDT pool', - 'cDAI+cUSDC+USDT', - '18', - ]; const dai = [ daiAddress, 'Dai Stablecoin', @@ -174,7 +168,7 @@ contract('CurveAdapter', () => { }); }); - it('should return correct full unit', async () => { + it('should return correct final full unit', async () => { await adapterRegistry.methods['getFinalFullTokenBalance(string,address)']( 'Curve pool token', ssCompoundTokenAddress, @@ -186,7 +180,7 @@ contract('CurveAdapter', () => { }); }); - it('should return 0 if wrong pool token address', async () => { + it('should not return 0 if wrong pool token address', async () => { await adapterRegistry.methods.getAdapterBalance( testAddress, protocolAdapterAddress, @@ -194,9 +188,7 @@ contract('CurveAdapter', () => { ) .call() .then((result) => { - assert.deepEqual(result.balances[0].base.metadata, ssUSDT); - assert.equal(result.balances[0].base.amount, 0); - assert.equal(result.balances[0].underlying.length, 0); + assert.deepEqual(result.balances[0].underlying, []); }); }); }); diff --git a/test/DyDxAssetAdapter.js b/test/DyDxAssetAdapter.js index d686c4e0..bb88d217 100755 --- a/test/DyDxAssetAdapter.js +++ b/test/DyDxAssetAdapter.js @@ -16,36 +16,12 @@ contract('DyDxAssetAdapter', () => { let adapterRegistry; let protocolAdapterAddress; let erc20TokenAdapterAddress; - const weth = [ - wethAddress, - 'Wrapped Ether', - 'WETH', - '18', - ]; const dai = [ daiAddress, 'Dai Stablecoin', 'DAI', '18', ]; - const sai = [ - saiAddress, - 'Sai Stablecoin v1.0', - 'SAI', - '18', - ]; - const bat = [ - batAddress, - 'Basic Attention Token', - 'BAT', - '18', - ]; - const usdc = [ - usdcAddress, - 'USD//C', - 'USDC', - '6', - ]; beforeEach(async () => { accounts = await web3.eth.getAccounts(); @@ -99,13 +75,7 @@ contract('DyDxAssetAdapter', () => { .call() .then((result) => { displayToken(result[0].adapterBalances[0].balances[0].base); - displayToken(result[0].adapterBalances[0].balances[1].base); - displayToken(result[0].adapterBalances[0].balances[2].base); - displayToken(result[0].adapterBalances[0].balances[3].base); - assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, weth); - assert.deepEqual(result[0].adapterBalances[0].balances[1].base.metadata, sai); - assert.deepEqual(result[0].adapterBalances[0].balances[2].base.metadata, usdc); - assert.deepEqual(result[0].adapterBalances[0].balances[3].base.metadata, dai); + assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, dai); }); }); @@ -117,9 +87,7 @@ contract('DyDxAssetAdapter', () => { ) .call() .then((result) => { - assert.deepEqual(result.balances[0].base.metadata, bat); - assert.equal(result.balances[0].base.amount, 0); - assert.equal(result.balances[0].underlying.length, 0); + assert.equal(result.balances, 0); }); }); }); diff --git a/test/DyDxDebtAdapter.js b/test/DyDxDebtAdapter.js index 99f8cb68..47578a0b 100755 --- a/test/DyDxDebtAdapter.js +++ b/test/DyDxDebtAdapter.js @@ -22,30 +22,6 @@ contract('DyDxDebtAdapter', () => { 'WETH', '18', ]; - const dai = [ - daiAddress, - 'Dai Stablecoin', - 'DAI', - '18', - ]; - const sai = [ - saiAddress, - 'Sai Stablecoin v1.0', - 'SAI', - '18', - ]; - const bat = [ - batAddress, - 'Basic Attention Token', - 'BAT', - '18', - ]; - const usdc = [ - usdcAddress, - 'USD//C', - 'USDC', - '6', - ]; beforeEach(async () => { accounts = await web3.eth.getAccounts(); @@ -99,17 +75,11 @@ contract('DyDxDebtAdapter', () => { .call() .then((result) => { displayToken(result[0].adapterBalances[0].balances[0].base); - displayToken(result[0].adapterBalances[0].balances[1].base); - displayToken(result[0].adapterBalances[0].balances[2].base); - displayToken(result[0].adapterBalances[0].balances[3].base); assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, weth); - assert.deepEqual(result[0].adapterBalances[0].balances[1].base.metadata, sai); - assert.deepEqual(result[0].adapterBalances[0].balances[2].base.metadata, usdc); - assert.deepEqual(result[0].adapterBalances[0].balances[3].base.metadata, dai); }); }); - it('should return 0 value for wrong asset', async () => { + it('should not return 0 value for wrong asset', async () => { await adapterRegistry.methods.getAdapterBalance( testAddress, protocolAdapterAddress, @@ -117,9 +87,7 @@ contract('DyDxDebtAdapter', () => { ) .call() .then((result) => { - assert.deepEqual(result.balances[0].base.metadata, bat); - assert.equal(result.balances[0].base.amount, 0); - assert.equal(result.balances[0].underlying.length, 0); + assert.equal(result.balances.length, 0); }); }); }); diff --git a/test/ERC20TokenAdapter.js b/test/ERC20TokenAdapter.js index e07cf328..79912cfb 100755 --- a/test/ERC20TokenAdapter.js +++ b/test/ERC20TokenAdapter.js @@ -1,23 +1,23 @@ -import displayToken from './helpers/displayToken'; +// import displayToken from './helpers/displayToken'; const AdapterRegistry = artifacts.require('./AdapterRegistry'); const ProtocolAdapter = artifacts.require('./SynthetixAssetAdapter'); const ERC20TokenAdapter = artifacts.require('./ERC20TokenAdapter'); -contract('SynthetixAssetAdapter', () => { +contract('ERC20TokenAdapter', () => { const badAddress = '0x101571584659dC31bF3E3E5E29F55D8BdfBAecEC'; - const testAddress = '0x42b9dF65B219B3dD36FF330A4dD8f327A6Ada990'; + // const testAddress = '0x42b9dF65B219B3dD36FF330A4dD8f327A6Ada990'; let accounts; let adapterRegistry; let protocolAdapterAddress; let erc20TokenAdapterAddress; - const bad = [ - badAddress, - 'Not available', - 'N/A', - '18', - ]; + // const bad = [ + // badAddress, + // 'Not available', + // 'N/A', + // '0', + // ]; beforeEach(async () => { accounts = await web3.eth.getAccounts(); @@ -63,17 +63,18 @@ contract('SynthetixAssetAdapter', () => { }); }); - it('should return n/a if symbol or name are not accessible', async () => { - await adapterRegistry.methods.getAdapterBalance( - testAddress, - protocolAdapterAddress, - [badAddress], - ) - .call() - .then((result) => { - displayToken(result.balances[0].base); - assert.deepEqual(result.balances[0].base.metadata, bad); - assert.equal(result.balances[0].underlying.length, 0); - }); - }); + // MUST be non-zero address for test + // it('should return n/a if symbol or name are not accessible', async () => { + // await adapterRegistry.methods.getAdapterBalance( + // testAddress, + // protocolAdapterAddress, + // [badAddress], + // ) + // .call() + // .then((result) => { + // displayToken(result.balances[0].base); + // assert.deepEqual(result.balances[0].base.metadata, bad); + // assert.equal(result.balances[0].underlying.length, 0); + // }); + // }); }); diff --git a/test/IdleAdapter.js b/test/IdleAdapter.js index 5b6b86ca..06a889ef 100644 --- a/test/IdleAdapter.js +++ b/test/IdleAdapter.js @@ -55,7 +55,7 @@ contract('IdleAdapter', () => { ]], [[[ idleDAIAddress, - idleUSDCAddress + idleUSDCAddress, ]]], ) .send({ diff --git a/test/IearnAdapter.js b/test/IearnAdapter.js index e20e608d..550aed6f 100755 --- a/test/IearnAdapter.js +++ b/test/IearnAdapter.js @@ -26,6 +26,12 @@ contract('IearnAdapter', () => { 'DAI', '18', ]; + const yDAIna = [ + yDAIAddress, + 'Not available', + 'N/A', + '0', + ]; beforeEach(async () => { accounts = await web3.eth.getAccounts(); @@ -88,4 +94,24 @@ contract('IearnAdapter', () => { assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[0].metadata, dai); }); }); + + it('should not fail if token adapter is missing', async () => { + await adapterRegistry.methods.removeTokenAdapters( + ['YToken'], + ) + .send({ + from: accounts[0], + gas: '1000000', + }); + await adapterRegistry.methods.getAdapterBalance( + testAddress, + protocolAdapterAddress, + [yDAIAddress], + ) + .call() + .then((result) => { + assert.deepEqual(result.balances[0].base.metadata, yDAIna); + assert.equal(result.balances[0].underlying.length, 0); + }); + }); }); diff --git a/test/MCDAssetAdapter.js b/test/MCDAssetAdapter.js index 4e61a988..4f0f8d54 100755 --- a/test/MCDAssetAdapter.js +++ b/test/MCDAssetAdapter.js @@ -2,17 +2,20 @@ import displayToken from './helpers/displayToken'; const AdapterRegistry = artifacts.require('./AdapterRegistry'); const ProtocolAdapter = artifacts.require('./MCDAssetAdapter'); +const DebtProtocolAdapter = artifacts.require('./MCDDebtAdapter'); const TokenAdapter = artifacts.require('./ERC20TokenAdapter'); contract('MCDAssetAdapter', () => { const wethAddress = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'; const batAddress = '0x0D8775F648430679A709E98d2b0Cb6250d2887EF'; + const daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; // for debt // DSProxy of '0x42b9dF65B219B3dD36FF330A4dD8f327A6Ada990' const testAddress = '0x29604c784102D453B476fB099b8DCfc83b508F55'; let accounts; let adapterRegistry; let protocolAdapterAddress; + let debtProtocolAdapterAddress; let tokenAdapterAddress; const weth = [ wethAddress, @@ -20,12 +23,6 @@ contract('MCDAssetAdapter', () => { 'WETH', '18', ]; - const bat = [ - batAddress, - 'Basic Attention Token', - 'BAT', - '18', - ]; beforeEach(async () => { accounts = await web3.eth.getAccounts(); @@ -33,6 +30,10 @@ contract('MCDAssetAdapter', () => { .then((result) => { protocolAdapterAddress = result.address; }); + await DebtProtocolAdapter.new({ from: accounts[0] }) + .then((result) => { + debtProtocolAdapterAddress = result.address; + }); await TokenAdapter.new({ from: accounts[0] }) .then((result) => { tokenAdapterAddress = result.address; @@ -51,12 +52,18 @@ contract('MCDAssetAdapter', () => { '0', ]], [[ + debtProtocolAdapterAddress, protocolAdapterAddress, ]], - [[[ - wethAddress, - batAddress, - ]]], + [[ + [ + daiAddress, + ], + [ + wethAddress, + batAddress, + ], + ]], ) .send({ from: accounts[0], @@ -77,11 +84,8 @@ contract('MCDAssetAdapter', () => { .call() .then((result) => { displayToken(result[0].adapterBalances[0].balances[0].base); - displayToken(result[0].adapterBalances[0].balances[1].base); assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, weth); - assert.deepEqual(result[0].adapterBalances[0].balances[1].base.metadata, bat); assert.equal(result[0].adapterBalances[0].balances[0].underlying.length, 0); - assert.equal(result[0].adapterBalances[0].balances[1].underlying.length, 0); }); }); }); diff --git a/test/MCDDebtAdapter.js b/test/MCDDebtAdapter.js index 3eacfea5..25c1a1f8 100755 --- a/test/MCDDebtAdapter.js +++ b/test/MCDDebtAdapter.js @@ -1,4 +1,4 @@ -import displayToken from './helpers/displayToken'; +// import displayToken from './helpers/displayToken'; const AdapterRegistry = artifacts.require('./AdapterRegistry'); const ProtocolAdapter = artifacts.require('./MCDDebtAdapter'); @@ -13,12 +13,6 @@ contract('MCDDebtAdapter', () => { let adapterRegistry; let protocolAdapterAddress; let tokenAdapterAddress; - const dai = [ - daiAddress, - 'Dai Stablecoin', - 'DAI', - '18', - ]; beforeEach(async () => { accounts = await web3.eth.getAccounts(); @@ -68,9 +62,7 @@ contract('MCDDebtAdapter', () => { await adapterRegistry.methods['getBalances(address)'](testAddress) .call() .then((result) => { - displayToken(result[0].adapterBalances[0].balances[0].base); - assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, dai); - assert.equal(result[0].adapterBalances[0].balances[0].underlying.length, 0); + assert.equal(result.length, 0); }); }); }); diff --git a/test/PoolTogetherAdapter.js b/test/PoolTogetherAdapter.js index bebb49c9..5d0305bb 100755 --- a/test/PoolTogetherAdapter.js +++ b/test/PoolTogetherAdapter.js @@ -6,7 +6,6 @@ const TokenAdapter = artifacts.require('./PoolTogetherTokenAdapter'); const ERC20TokenAdapter = artifacts.require('./ERC20TokenAdapter'); contract('PoolTogetherAdapter', () => { - const saiAddress = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359'; const daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; const usdcAddress = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'; @@ -27,12 +26,6 @@ contract('PoolTogetherAdapter', () => { 'DAI', '18', ]; - const sai = [ - saiAddress, - 'Sai Stablecoin v1.0', - 'SAI', - '18', - ]; const usdc = [ usdcAddress, 'USD//C', @@ -45,12 +38,6 @@ contract('PoolTogetherAdapter', () => { 'PLT', '18', ]; - const saiPool = [ - saiPoolAddress, - 'SAI pool', - 'PLT', - '18', - ]; const usdcPool = [ usdcPoolAddress, 'USDC pool', @@ -108,19 +95,16 @@ contract('PoolTogetherAdapter', () => { }); }); - it.only('should return correct balances', async () => { + it('should return correct balances', async () => { await adapterRegistry.methods['getBalances(address)'](testAddress) .call() .then((result) => { displayToken(result[0].adapterBalances[0].balances[0].underlying[0]); displayToken(result[0].adapterBalances[0].balances[1].underlying[0]); - displayToken(result[0].adapterBalances[0].balances[2].underlying[0]); - assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, saiPool); - assert.deepEqual(result[0].adapterBalances[0].balances[1].base.metadata, daiPool); - assert.deepEqual(result[0].adapterBalances[0].balances[2].base.metadata, usdcPool); - assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[0].metadata, sai); - assert.deepEqual(result[0].adapterBalances[0].balances[1].underlying[0].metadata, dai); - assert.deepEqual(result[0].adapterBalances[0].balances[2].underlying[0].metadata, usdc); + assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, daiPool); + assert.deepEqual(result[0].adapterBalances[0].balances[1].base.metadata, usdcPool); + assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[0].metadata, dai); + assert.deepEqual(result[0].adapterBalances[0].balances[1].underlying[0].metadata, usdc); }); }); }); diff --git a/test/UniswapV1Adapter.js b/test/UniswapV1Adapter.js index 92f84137..bab0e795 100755 --- a/test/UniswapV1Adapter.js +++ b/test/UniswapV1Adapter.js @@ -6,7 +6,7 @@ const TokenAdapter = artifacts.require('./UniswapV1TokenAdapter'); const CompoundTokenAdapter = artifacts.require('./CompoundTokenAdapter'); const ERC20TokenAdapter = artifacts.require('./ERC20TokenAdapter'); -contract('UniswapAdapter', () => { +contract('UniswapV1Adapter', () => { const batUniAddress = '0x2E642b8D59B45a1D8c5aEf716A84FF44ea665914'; const mkrUniAddress = '0x2C4Bd064b998838076fa341A83d007FC2FA50957'; const daiUniAddress = '0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667'; @@ -14,14 +14,14 @@ contract('UniswapAdapter', () => { const snxUniAddress = '0x3958B4eC427F8fa24eB60F42821760e88d485f7F'; const saiUniAddress = '0x09cabEC1eAd1c0Ba254B09efb3EE13841712bE14'; const cDaiUniAddress = '0x34E89740adF97C3A9D3f63Cc2cE4a914382c230b'; + const cSaiUniAddress = '0x45A2FDfED7F7a2c791fb1bdF6075b83faD821ddE'; const batAddress = '0x0D8775F648430679A709E98d2b0Cb6250d2887EF'; - const mkrAddress = '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2'; const daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; + const mkrAddress = '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2'; const usdcAddress = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'; const snxAddress = '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F'; const saiAddress = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359'; const ethAddress = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'; - const cDaiAddress = '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643'; const testAddress = '0x42b9dF65B219B3dD36FF330A4dD8f327A6Ada990'; let accounts; @@ -66,9 +66,9 @@ contract('UniswapAdapter', () => { 'UNI-V1', '18', ]; - const cDaiUni = [ - cDaiUniAddress, - 'cDAI pool', + const cSaiUni = [ + cSaiUniAddress, + 'cSAI pool', 'UNI-V1', '18', ]; @@ -78,11 +78,11 @@ contract('UniswapAdapter', () => { 'DAI', '18', ]; - const cDai = [ - cDaiAddress, - 'Compound Dai', - 'cDAI', - '8', + const mkr = [ + mkrAddress, + 'Maker', + 'MKR', + '18', ]; const usdc = [ usdcAddress, @@ -114,12 +114,6 @@ contract('UniswapAdapter', () => { 'BAT', '18', ]; - const mkr = [ - mkrAddress, - 'Maker', - 'MKR', - '18', - ]; beforeEach(async () => { accounts = await web3.eth.getAccounts(); @@ -163,6 +157,7 @@ contract('UniswapAdapter', () => { snxUniAddress, saiUniAddress, cDaiUniAddress, + cSaiUniAddress, ]]], ) .send({ @@ -183,18 +178,25 @@ contract('UniswapAdapter', () => { await adapterRegistry.methods['getBalances(address)'](testAddress) .call() .then((result) => { + displayToken(result[0].adapterBalances[0].balances[0].base); displayToken(result[0].adapterBalances[0].balances[0].underlying[0]); displayToken(result[0].adapterBalances[0].balances[0].underlying[1]); + displayToken(result[0].adapterBalances[0].balances[1].base); displayToken(result[0].adapterBalances[0].balances[1].underlying[0]); displayToken(result[0].adapterBalances[0].balances[1].underlying[1]); + displayToken(result[0].adapterBalances[0].balances[2].base); displayToken(result[0].adapterBalances[0].balances[2].underlying[0]); displayToken(result[0].adapterBalances[0].balances[2].underlying[1]); + displayToken(result[0].adapterBalances[0].balances[3].base); displayToken(result[0].adapterBalances[0].balances[3].underlying[0]); displayToken(result[0].adapterBalances[0].balances[3].underlying[1]); + displayToken(result[0].adapterBalances[0].balances[4].base); displayToken(result[0].adapterBalances[0].balances[4].underlying[0]); displayToken(result[0].adapterBalances[0].balances[4].underlying[1]); + displayToken(result[0].adapterBalances[0].balances[5].base); displayToken(result[0].adapterBalances[0].balances[5].underlying[0]); displayToken(result[0].adapterBalances[0].balances[5].underlying[1]); + displayToken(result[0].adapterBalances[0].balances[6].base); displayToken(result[0].adapterBalances[0].balances[6].underlying[0]); displayToken(result[0].adapterBalances[0].balances[6].underlying[1]); assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[0].metadata, eth); @@ -210,14 +212,14 @@ contract('UniswapAdapter', () => { assert.deepEqual(result[0].adapterBalances[0].balances[3].base.metadata, usdcUni); assert.deepEqual(result[0].adapterBalances[0].balances[4].base.metadata, snxUni); assert.deepEqual(result[0].adapterBalances[0].balances[5].base.metadata, saiUni); - assert.deepEqual(result[0].adapterBalances[0].balances[6].base.metadata, cDaiUni); + assert.deepEqual(result[0].adapterBalances[0].balances[6].base.metadata, cSaiUni); assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[1].metadata, bat); assert.deepEqual(result[0].adapterBalances[0].balances[1].underlying[1].metadata, mkr); assert.deepEqual(result[0].adapterBalances[0].balances[2].underlying[1].metadata, dai); assert.deepEqual(result[0].adapterBalances[0].balances[3].underlying[1].metadata, usdc); assert.deepEqual(result[0].adapterBalances[0].balances[4].underlying[1].metadata, snx); assert.deepEqual(result[0].adapterBalances[0].balances[5].underlying[1].metadata, sai); - assert.deepEqual(result[0].adapterBalances[0].balances[6].underlying[1].metadata, cDai); + assert.deepEqual(result[0].adapterBalances[0].balances[6].underlying[1].metadata, sai); }); }); }); diff --git a/truffle.js b/truffle.js index 513cce38..8cfd7a11 100755 --- a/truffle.js +++ b/truffle.js @@ -38,11 +38,11 @@ module.exports = { }, compilers: { solc: { - version: '0.6.4', + version: '0.6.5', settings: { optimizer: { enabled: true, - runs: 200, + runs: 10000, }, }, },