From f6f788304a7b36a972e231a3768bd1ab178927b5 Mon Sep 17 00:00:00 2001 From: Ali Nuraldin Date: Fri, 3 Apr 2020 12:49:35 +0200 Subject: [PATCH] Opium Network Adapters + Tests --- .solhintignore | 1 + .soliumignore | 1 + .../adapters/opium/OpiumAssetAdapter.sol | 52 +++++++++++ contracts/adapters/opium/OpiumHelpers.sol | 52 +++++++++++ .../adapters/opium/OpiumTokenAdapter.sol | 53 +++++++++++ test/OpiumAdapter.js | 92 +++++++++++++++++++ test/PoolTogetherAdapter.js | 2 +- 7 files changed, 252 insertions(+), 1 deletion(-) create mode 100755 contracts/adapters/opium/OpiumAssetAdapter.sol create mode 100755 contracts/adapters/opium/OpiumHelpers.sol create mode 100755 contracts/adapters/opium/OpiumTokenAdapter.sol create mode 100755 test/OpiumAdapter.js diff --git a/.solhintignore b/.solhintignore index b6bba3dc..da1d0db6 100755 --- a/.solhintignore +++ b/.solhintignore @@ -3,3 +3,4 @@ node_modules ./contracts/Structs.sol ./contracts/adapters/maker/MKRAdapter.sol ./contracts/adapters/dydx +./contracts/adapters/opium diff --git a/.soliumignore b/.soliumignore index d9ec197b..23abc8e8 100755 --- a/.soliumignore +++ b/.soliumignore @@ -9,3 +9,4 @@ node_modules ./contracts/adapters/maker/MKRAdapter.sol ./contracts/adapters/uniswap/UniswapTokenAdapter.sol ./contracts/adapters/dydx +./contracts/adapters/opium diff --git a/contracts/adapters/opium/OpiumAssetAdapter.sol b/contracts/adapters/opium/OpiumAssetAdapter.sol new file mode 100755 index 00000000..09e87fb8 --- /dev/null +++ b/contracts/adapters/opium/OpiumAssetAdapter.sol @@ -0,0 +1,52 @@ +// 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.4; +pragma experimental ABIEncoderV2; + +import { ProtocolAdapter } from "../ProtocolAdapter.sol"; +import { OpiumAdapter, OpiumTokenMinter } from "./OpiumHelpers.sol"; + +/** + * @title Asset adapter for Opium protocol. + * @dev Implementation of ProtocolAdapter interface. + * @author Ali Nuraldin + */ +contract OpiumAssetAdapter is ProtocolAdapter, OpiumAdapter { + + /** + * @return Type of the adapter. + * @dev Implementation of ProtocolAdapter interface function. + */ + function adapterType() external pure override returns (string memory) { + return "Asset"; + } + + /** + * @return Type of the token used in adapter. + * @dev Implementation of ProtocolAdapter interface function. + */ + function tokenType() external pure override returns (string memory) { + return "ERC721o"; + } + + /** + * @return Amount of position tokens held by the given account. + * @dev Implementation of ProtocolAdapter interface function. + */ + function getBalance(address token, address account) external view override returns (uint256) { + return OpiumTokenMinter(token).balanceOf(account); + } +} diff --git a/contracts/adapters/opium/OpiumHelpers.sol b/contracts/adapters/opium/OpiumHelpers.sol new file mode 100755 index 00000000..e602192a --- /dev/null +++ b/contracts/adapters/opium/OpiumHelpers.sol @@ -0,0 +1,52 @@ +// 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.4; +pragma experimental ABIEncoderV2; + + +/** + * @dev Opium adapter abstract contract. + * @dev Base contract for Opium adapters. + * @author Ali Nuraldin + */ +abstract contract OpiumAdapter { + address internal constant TOKEN_MINTER = 0x9Dd91d61A7aa58537fCdbf16fD21bE25731341B3; +} + +/** + * @dev Opium TokenMinter contract interface. + * @author Ali Nuraldin + */ +interface OpiumTokenMinter { + /** + * @dev ERC721 interface compatible function for position token name retrieving + * @return Returns name of token + */ + function name() external view returns (string memory); + + /** + * @notice ERC721 interface compatible function for position token symbol retrieving + * @return Returns symbol of token + */ + function symbol() external view returns (string memory); + + /** + * @dev Gets the number of different tokenIds owned by the address we are checking + * @param _owner The adddress we are checking + * @return balance The unique amount of tokens owned + */ + function balanceOf(address _owner) external view returns (uint256); +} diff --git a/contracts/adapters/opium/OpiumTokenAdapter.sol b/contracts/adapters/opium/OpiumTokenAdapter.sol new file mode 100755 index 00000000..6a15130b --- /dev/null +++ b/contracts/adapters/opium/OpiumTokenAdapter.sol @@ -0,0 +1,53 @@ +// 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.4; +pragma experimental ABIEncoderV2; + +import { TokenAdapter } from "../TokenAdapter.sol"; +import { OpiumAdapter, OpiumTokenMinter } from "./OpiumHelpers.sol"; + +import { TokenMetadata, Component } from "../../Structs.sol"; + +/** + * @title Token adapter for Opium Position token. + * @dev Implementation of TokenAdapter interface. + * @author Ali Nuraldin + */ +contract OpiumTokenAdapter is TokenAdapter, OpiumAdapter { + + /** + * @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: OpiumTokenMinter(token).name(), + symbol: OpiumTokenMinter(token).symbol(), + decimals: 0 + }); + } + + /** + * @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) { + token; + Component[] memory underlyingTokens = new Component[](0); + return underlyingTokens; + } +} diff --git a/test/OpiumAdapter.js b/test/OpiumAdapter.js new file mode 100755 index 00000000..81c140a1 --- /dev/null +++ b/test/OpiumAdapter.js @@ -0,0 +1,92 @@ +const AdapterRegistry = artifacts.require('./AdapterRegistry'); +const OpiumAssetAdapter = artifacts.require('./OpiumAssetAdapter'); +const OpiumTokenAdapter = artifacts.require('./OpiumTokenAdapter'); + +contract('OpiumAdapter', () => { + const OPIUM_TOKEN_ADDRESS = '0x9Dd91d61A7aa58537fCdbf16fD21bE25731341B3'; + + const testAddress = '0xed56b70ec9ebe6127d4caf97872d759a1b380d61'; + + let accounts; + let adapterRegistry; + let protocolAdapterAddress; + let tokenAdapterAddress; + + beforeEach(async () => { + accounts = await web3.eth.getAccounts(); + + // Opium Asset Adapter + await OpiumAssetAdapter.new({ from: accounts[0] }) + .then((result) => { + protocolAdapterAddress = result.address; + }); + + // Opium token Adapter + await OpiumTokenAdapter.new({ from: accounts[0] }) + .then((result) => { + tokenAdapterAddress = result.address; + }); + + // Adapter registry + await AdapterRegistry.new({ from: accounts[0] }) + .then((result) => { + adapterRegistry = result.contract; + }); + + // Add ProtocolAdapters to AdapterRegistry + await adapterRegistry.methods.addProtocols( + ['Opium Network'], + [[ + 'Mock Protocol Name', + 'Mock protocol description', + 'Mock website', + 'Mock icon', + '0', + ]], + [[ + protocolAdapterAddress, + ]], + [[[ + OPIUM_TOKEN_ADDRESS, + ]]], + ) + .send({ + from: accounts[0], + gas: '1000000', + }); + + // Add TokenAdapters to AdapterRegistry + await adapterRegistry.methods.addTokenAdapters( + ['ERC721o'], + [tokenAdapterAddress], + ) + .send({ + from: accounts[0], + gas: '300000', + }); + }); + + it.only('should return correct balances', async () => { + await adapterRegistry.methods['getBalances(address)'](testAddress) + .call() + .then((result) => { + // Adapter Metadata + assert.equal(result[0].adapterBalances[0].metadata.adapterAddress, protocolAdapterAddress); + assert.equal(result[0].adapterBalances[0].metadata.adapterType, 'Asset'); + + // Balances Base Metadata + assert.equal( + result[0].adapterBalances[0].balances[0].base.metadata.token, OPIUM_TOKEN_ADDRESS + ); + assert.equal(result[0].adapterBalances[0].balances[0].base.metadata.name, 'Opium Network Position Token'); + assert.equal(result[0].adapterBalances[0].balances[0].base.metadata.symbol, 'ONP'); + assert.equal(result[0].adapterBalances[0].balances[0].base.metadata.decimals, 0); + + // Balances Base Amount + assert.exists(result[0].adapterBalances[0].balances[0].base.amount); + + // Balances Underlying length + assert.equal(result[0].adapterBalances[0].balances[0].underlying.length, 0); + }); + }); +}); diff --git a/test/PoolTogetherAdapter.js b/test/PoolTogetherAdapter.js index bebb49c9..86b514fd 100755 --- a/test/PoolTogetherAdapter.js +++ b/test/PoolTogetherAdapter.js @@ -108,7 +108,7 @@ contract('PoolTogetherAdapter', () => { }); }); - it.only('should return correct balances', async () => { + it('should return correct balances', async () => { await adapterRegistry.methods['getBalances(address)'](testAddress) .call() .then((result) => {