Skip to content

Commit f30794e

Browse files
authored
Merge pull request #36 from MickdeGraaf/feature/btc++
PieDAO Pie Tokens
2 parents 89542e2 + 74ecf57 commit f30794e

File tree

3 files changed

+253
-0
lines changed

3 files changed

+253
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (C) 2020 Zerion Inc. <https://zerion.io>
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU General Public License as published by
5+
// the Free Software Foundation, either version 3 of the License, or
6+
// (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU General Public License
14+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
16+
pragma solidity 0.6.5;
17+
pragma experimental ABIEncoderV2;
18+
19+
import { ERC20 } from "../../ERC20.sol";
20+
import { ProtocolAdapter } from "../ProtocolAdapter.sol";
21+
22+
23+
/**
24+
* @title Adapter for PieDAO pools.
25+
* @dev Implementation of ProtocolAdapter interface.
26+
* @author Mick de Graaf <mick@dexlab.io>
27+
*/
28+
contract PieDAOPieAdapter is ProtocolAdapter {
29+
30+
string public constant override adapterType = "Asset";
31+
32+
string public constant override tokenType = "PieDAO Pie Token";
33+
34+
/**
35+
* @return Amount of PieDAO pool tokens held by the given account.
36+
* @param token Address of the pool!
37+
* @dev Implementation of ProtocolAdapter interface function.
38+
*/
39+
function getBalance(address token, address account) external view override returns (uint256) {
40+
return ERC20(token).balanceOf(account);
41+
}
42+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright (C) 2020 Zerion Inc. <https://zerion.io>
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU General Public License as published by
5+
// the Free Software Foundation, either version 3 of the License, or
6+
// (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU General Public License
14+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
16+
pragma solidity 0.6.5;
17+
pragma experimental ABIEncoderV2;
18+
19+
import { ERC20 } from "../../ERC20.sol";
20+
import { TokenMetadata, Component } from "../../Structs.sol";
21+
import { TokenAdapter } from "../TokenAdapter.sol";
22+
23+
24+
/**
25+
* @dev PieSmartPool contract interface.
26+
* Only the functions required for UniswapAdapter contract are added.
27+
* The BPool contract is available here
28+
* github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol.
29+
*/
30+
interface IPieSmartPool {
31+
function getTokens() external view returns (address[] memory);
32+
function getBPool() external view returns (address);
33+
}
34+
35+
36+
/**
37+
* @dev BPool contract interface.
38+
* Only the functions required for UniswapAdapter contract are added.
39+
* The BPool contract is available here
40+
* github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol.
41+
*/
42+
interface BPool {
43+
function getFinalTokens() external view returns (address[] memory);
44+
function getBalance(address) external view returns (uint256);
45+
function getNormalizedWeight(address) external view returns (uint256);
46+
}
47+
48+
49+
/**
50+
* @title Token adapter for Pie pool tokens.
51+
* @dev Implementation of TokenAdapter interface.
52+
* @author Mick de Graaf <mick@dexlab.io>
53+
*/
54+
contract PieDAOPieTokenAdapter is TokenAdapter {
55+
56+
/**
57+
* @return TokenMetadata struct with ERC20-style token info.
58+
* @dev Implementation of TokenAdapter interface function.
59+
*/
60+
function getMetadata(address token) external view override returns (TokenMetadata memory) {
61+
return TokenMetadata({
62+
token: token,
63+
name: ERC20(token).name(),
64+
symbol: ERC20(token).symbol(),
65+
decimals: ERC20(token).decimals()
66+
});
67+
}
68+
69+
/**
70+
* @return Array of Component structs with underlying tokens rates for the given asset.
71+
* @dev Implementation of TokenAdapter interface function.
72+
*/
73+
function getComponents(address token) external view override returns (Component[] memory) {
74+
address[] memory underlyingTokensAddresses = IPieSmartPool(token).getTokens();
75+
uint256 totalSupply = ERC20(token).totalSupply();
76+
BPool bPool = BPool(IPieSmartPool(token).getBPool());
77+
78+
Component[] memory underlyingTokens = new Component[](underlyingTokensAddresses.length);
79+
address underlyingToken;
80+
81+
for (uint256 i = 0; i < underlyingTokens.length; i++) {
82+
underlyingToken = underlyingTokensAddresses[i];
83+
underlyingTokens[i] = Component({
84+
token: underlyingToken,
85+
tokenType: "ERC20",
86+
rate: bPool.getBalance(underlyingToken) * 1e18 / totalSupply
87+
});
88+
}
89+
90+
return underlyingTokens;
91+
}
92+
93+
}

test/PieDAOPieAdapter.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import displayToken from './helpers/displayToken';
2+
3+
const AdapterRegistry = artifacts.require('./AdapterRegistry');
4+
const ProtocolAdapter = artifacts.require('./PieDAOPieAdapter');
5+
const TokenAdapter = artifacts.require('./PieDAOPieTokenAdapter');
6+
const ERC20TokenAdapter = artifacts.require('./ERC20TokenAdapter');
7+
8+
contract('PieDAOPieAdapter', () => {
9+
const BTCPPAddress = '0x0327112423F3A68efdF1fcF402F6c5CB9f7C33fd';
10+
const wbtcAddress = '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599';
11+
const pbtcAddress = '0x5228a22e72ccC52d415EcFd199F99D0665E7733b';
12+
const imbtcAddress = '0x3212b29E33587A00FB1C83346f5dBFA69A458923';
13+
const sbtcAddress = '0xfE18be6b3Bd88A2D2A7f928d00292E7a9963CfC6';
14+
15+
const testAddress = '0xd4DBF96Db2FDf8ED40296d8d104b371aDF7dEE12';
16+
17+
let accounts;
18+
let adapterRegistry;
19+
let protocolAdapterAddress;
20+
let tokenAdapterAddress;
21+
let erc20TokenAdapterAddress;
22+
23+
const btcpp = [
24+
BTCPPAddress,
25+
'PieDAO BTC++',
26+
'BTC++',
27+
'18',
28+
];
29+
const wbtc = [
30+
wbtcAddress,
31+
'Wrapped BTC',
32+
'WBTC',
33+
'8',
34+
];
35+
const pbtc = [
36+
pbtcAddress,
37+
'pTokens BTC',
38+
'pBTC',
39+
'18',
40+
];
41+
const imbtc = [
42+
imbtcAddress,
43+
'The Tokenized Bitcoin',
44+
'imBTC',
45+
'8',
46+
];
47+
const sbtc = [
48+
sbtcAddress,
49+
'Synth sBTC',
50+
'sBTC',
51+
'18',
52+
];
53+
54+
beforeEach(async () => {
55+
accounts = await web3.eth.getAccounts();
56+
await ProtocolAdapter.new({ from: accounts[0] })
57+
.then((result) => {
58+
protocolAdapterAddress = result.address;
59+
});
60+
await TokenAdapter.new({ from: accounts[0] })
61+
.then((result) => {
62+
tokenAdapterAddress = result.address;
63+
});
64+
await ERC20TokenAdapter.new({ from: accounts[0] })
65+
.then((result) => {
66+
erc20TokenAdapterAddress = result.address;
67+
});
68+
await AdapterRegistry.new({ from: accounts[0] })
69+
.then((result) => {
70+
adapterRegistry = result.contract;
71+
});
72+
await adapterRegistry.methods.addProtocols(
73+
['PieDAOPie'],
74+
[[
75+
'Mock Protocol Name',
76+
'Mock protocol description',
77+
'Mock website',
78+
'Mock icon',
79+
'0',
80+
]],
81+
[[
82+
protocolAdapterAddress,
83+
]],
84+
[[[
85+
BTCPPAddress
86+
]]],
87+
)
88+
.send({
89+
from: accounts[0],
90+
gas: '1000000',
91+
});
92+
await adapterRegistry.methods.addTokenAdapters(
93+
['ERC20', 'PieDAO Pie Token'],
94+
[erc20TokenAdapterAddress, tokenAdapterAddress],
95+
)
96+
.send({
97+
from: accounts[0],
98+
gas: '1000000',
99+
});
100+
});
101+
102+
it('should return correct balances', async () => {
103+
await adapterRegistry.methods['getBalances(address)'](testAddress)
104+
.call()
105+
.then((result) => {
106+
displayToken(result[0].adapterBalances[0].balances[0].underlying[0]);
107+
displayToken(result[0].adapterBalances[0].balances[0].underlying[1]);
108+
displayToken(result[0].adapterBalances[0].balances[0].underlying[2]);
109+
displayToken(result[0].adapterBalances[0].balances[0].underlying[3]);
110+
displayToken(result[0].adapterBalances[0].balances[0].base);
111+
assert.deepEqual(result[0].adapterBalances[0].balances[0].base.metadata, btcpp);
112+
assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[0].metadata, wbtc);
113+
assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[1].metadata, pbtc);
114+
assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[2].metadata, imbtc);
115+
assert.deepEqual(result[0].adapterBalances[0].balances[0].underlying[3].metadata, sbtc);
116+
});
117+
});
118+
});

0 commit comments

Comments
 (0)