WIP: done with registry test cases

This commit is contained in:
Thrilok Kumar 2020-08-30 23:33:16 +05:30
parent 25511f0629
commit a7fae35c8b
14 changed files with 11812 additions and 188 deletions

View File

@ -30,7 +30,7 @@ interface RateInterface {
function getTotalToken() external returns (uint totalUnderlyingTkn);
}
contract PoolToken is ReentrancyGuard, ERC20Pausable, DSMath {
contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath {
using SafeERC20 for IERC20;
event LogDeploy(address indexed token, uint amount);

View File

@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.8;
interface TokenInterface {
function balanceOf(address) external view returns (uint);
function transfer(address, uint) external returns (bool);
}
contract DaiRateLogic {
address poolToken;
TokenInterface baseToken;
function getTotalToken() public returns (uint) {
uint bal = baseToken.balanceOf(address(this));
bal += baseToken.balanceOf(address(poolToken));
return bal;
}
function reduceDai(uint amt) public {
baseToken.transfer(address(this), amt);
}
constructor (address daiPool, address dai) public {
poolToken = address(daiPool);
baseToken = TokenInterface(address(dai));
}
}

View File

@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.8;
contract EthRateLogic {
address poolToken;
function getTotalToken() public returns (uint) {
uint bal = (address(this).balance);
bal += (address(poolToken).balance);
return bal;
}
function reduceETH(uint amt) public {
payable(address(0)).transfer(amt);
}
constructor (address ethPool) public {
poolToken = address(ethPool);
}
}

4
migrations/2_registry.js Normal file
View File

@ -0,0 +1,4 @@
const Registry = artifacts.require("Registry");
module.exports = async function(deployer, networks, accounts) {
await deployer.deploy(Registry, accounts[0]); //deploy registry.sol contract
};

10
migrations/3_erc20Pool.js Normal file
View File

@ -0,0 +1,10 @@
const PoolToken = artifacts.require("PoolToken");
const DaiRateLogic = artifacts.require("DaiRateLogic");
const Registry = artifacts.require("Registry");
module.exports = async function(deployer, networks, accounts) {
var DAI_Addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
var registryInstance = await Registry.deployed();
var daiPoolInstance = await deployer.deploy(PoolToken, registryInstance.address, "Insta DAI", "IDAI", DAI_Addr);
var daiRateInstance = await deployer.deploy(DaiRateLogic, daiPoolInstance.address, DAI_Addr);
};

11
migrations/4_ethPool.js Normal file
View File

@ -0,0 +1,11 @@
const PoolETH = artifacts.require("PoolETH");
const Registry = artifacts.require("Registry");
const EthRateLogic = artifacts.require("EthRateLogic");
module.exports = async function(deployer, networks, accounts) {
var ETH_Addr = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
var registryInstance = await Registry.deployed();
var ethPoolInstance = await deployer.deploy(PoolETH, registryInstance.address, "Insta ETH", "IETH", ETH_Addr);
var ethRateInstance = await deployer.deploy(EthRateLogic, ethPoolInstance.address);
};

11372
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,9 @@
"description": "DSA Yield ERC20 Pool Contract",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"deploy:fork": "truffle deploy",
"test:fork": "truffle test",
"ganache:fork": "dotenv -- cross-var ganache-cli --fork https://mainnet.infura.io/v3/%INFURA_KEY% --unlock 0xfCD22438AD6eD564a1C26151Df73F6B33B817B56 --unlock 0x6b175474e89094c44da98b954eedeac495271d0f --u 0x9eb7f2591ed42dee9315b6e2aaf21ba85ea69f8c"
},
"repository": {
"type": "git",
@ -18,7 +20,11 @@
"homepage": "https://github.com/InstaDApp/dsa-yield-contract#readme",
"dependencies": {
"@openzeppelin/contracts": "^3.1.0",
"cross-var": "^1.1.0",
"dotenv": "^7.0.0",
"dotenv-cli": "^3.2.0",
"solc": "^0.6.8",
"chai": "^4.2.0",
"truffle-assertions": "^0.9.2",
"truffle-hdwallet-provider": "^1.0.17",
"truffle-typings": "^1.0.8",
@ -26,6 +32,7 @@
},
"devDependencies": {
"@nomiclabs/buidler": "^1.4.3",
"@nomiclabs/buidler-ganache": "^1.3.3",
"@nomiclabs/buidler-truffle5": "^1.3.4",
"@nomiclabs/buidler-web3": "^1.3.4",
"@openzeppelin/test-helpers": "^0.5.6",

5
scripts/utils.js Normal file
View File

@ -0,0 +1,5 @@
module.exports.asyncForEach = async (array, callback) => {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
};

122
test/1_registry.js Normal file
View File

@ -0,0 +1,122 @@
const { BN, ether, balance } = require('@openzeppelin/test-helpers');
const { expect } = require('chai');
const RegistryContract = artifacts.require("Registry");
const PoolTokenContract = artifacts.require("PoolToken");
const PoolETHContract = artifacts.require("PoolETH");
const DaiRateLogic = artifacts.require("DaiRateLogic");
const EthRateLogic = artifacts.require("EthRateLogic");
const masterAddr = "0xfCD22438AD6eD564a1C26151Df73F6B33B817B56"
contract('Registry.sol', async accounts => {
let ethAddr = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
let daiAddr = "0x6b175474e89094c44da98b954eedeac495271d0f";
let defaultAddr = "0x0000000000000000000000000000000000000000";
let ethPoolInstance;
let daiPoolInstance;
let registryInstance;
let ethRateLogicInstance;
let daiRateLogicInstance;
before(async() => {
registryInstance = await RegistryContract.deployed();
ethPoolInstance = await PoolETHContract.deployed();
daiPoolInstance = await PoolTokenContract.deployed();
ethRateLogicInstance = await EthRateLogic.deployed();
daiRateLogicInstance = await DaiRateLogic.deployed();
})
it('should send ether to the Master address', async () => {
await web3.eth.sendTransaction({
from: accounts[0],
to: masterAddr,
value: ether('10')
});
const ethBalance = await balance.current(masterAddr);
expect(new BN(ethBalance)).to.be.bignumber.least(new BN(ether('10')));
});
it('should add ETH pool in registry', async () => {
await addPool(registryInstance, ethPoolInstance.address, ethAddr);
});
it('should enable ETH pool in registry', async () => {
await enablePool(registryInstance, ethPoolInstance.address);
});
it('should remove ETH pool in registry', async () => {
await removePool(registryInstance, ethAddr);
});
it('should disable ETH pool in registry', async () => {
await disablePool(registryInstance, ethPoolInstance.address);
});
it('should add ETH pool in registry', async () => {
await addPool(registryInstance, ethPoolInstance.address, ethAddr);
});
it('should enable ETH pool in registry', async () => {
await enablePool(registryInstance, ethPoolInstance.address);
});
it('should add DAI pool in registry', async () => {
await addPool(registryInstance, daiPoolInstance.address, daiAddr);
});
it('should enable DAI pool in registry', async () => {
await enablePool(registryInstance, daiPoolInstance.address);
});
it('should update ETH Logic contract in registry', async () => {
await updateRateLogic(registryInstance, ethPoolInstance.address, ethRateLogicInstance.address);
});
it('should update DAI Logic contract in registry', async () => {
await updateRateLogic(registryInstance, daiPoolInstance.address, daiRateLogicInstance.address);
});
});
async function addPool(registryInstance, poolAddr, tokenAddr) {
await registryInstance.addPool(tokenAddr, poolAddr, {from: masterAddr});
var _poolAddr = await registryInstance.poolToken(tokenAddr);
expect(_poolAddr).to.equal(poolAddr);
}
async function removePool(registryInstance, tokenAddr) {
await registryInstance.removePool(tokenAddr, {from: masterAddr});
var _poolAddr = await registryInstance.poolToken(tokenAddr);
expect(_poolAddr).to.equal("0x0000000000000000000000000000000000000000");
}
async function enablePool(registryInstance, poolAddr) {
await registryInstance.updatePool(poolAddr, {from: masterAddr});
var _isPool = await registryInstance.isPool(poolAddr);
expect(_isPool).to.equal(true);
}
async function disablePool(registryInstance, poolAddr) {
await registryInstance.updatePool(poolAddr, {from: masterAddr});
var _isPool = await registryInstance.isPool(poolAddr);
expect(_isPool).to.equal(false);
}
async function updateRateLogic(registryInstance, poolAddr, logicAddr) {
await registryInstance.updatePoolLogic(poolAddr, logicAddr, {from: masterAddr});
var _logicAddr = await registryInstance.poolLogic(poolAddr);
expect(_logicAddr).to.equal(logicAddr);
}

82
test/2_daiPool.js Normal file
View File

@ -0,0 +1,82 @@
const { BN, ether, balance } = require('@openzeppelin/test-helpers');
const { expect } = require('chai');
const RegistryContract = artifacts.require("Registry");
const PoolTokenContract = artifacts.require("PoolToken");
const PoolETHContract = artifacts.require("PoolETH");
const DaiRateLogic = artifacts.require("DaiRateLogic");
const EthRateLogic = artifacts.require("EthRateLogic");
const masterAddr = "0xfCD22438AD6eD564a1C26151Df73F6B33B817B56"
// ABI
const daiABI = require('./abi/erc20');
const userAddress = '0x9eb7f2591ed42dee9315b6e2aaf21ba85ea69f8c';
const daiAddress = '0x6b175474e89094c44da98b954eedeac495271d0f';
const daiContract = new web3.eth.Contract(daiABI, daiAddress);
contract('DAI Pool', async accounts => {
let ethAddr = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
let daiAddr = "0x6b175474e89094c44da98b954eedeac495271d0f";
let defaultAddr = "0x0000000000000000000000000000000000000000";
let ethPoolInstance;
let daiPoolInstance;
let registryInstance;
let ethRateLogicInstance;
let daiRateLogicInstance;
before(async() => {
registryInstance = await RegistryContract.deployed();
ethPoolInstance = await PoolETHContract.deployed();
daiPoolInstance = await PoolTokenContract.deployed();
ethRateLogicInstance = await EthRateLogic.deployed();
daiRateLogicInstance = await DaiRateLogic.deployed();
})
it('should send ether to the user address', async () => {
// Send 1 eth to userAddress to have gas to send an ERC20 tx.
await web3.eth.sendTransaction({
from: accounts[0],
to: userAddress,
value: ether('1')
});
const ethBalance = await balance.current(userAddress);
expect(new BN(ethBalance)).to.be.bignumber.least(new BN(ether('1')));
});
it('should give DAI allowance for DAI pool', async () => {
await daiContract.methods
.approve(daiPoolInstance.address, ether('1000').toString())
.send({ from: userAddress});
const daiBalance = await daiContract.methods.allowance(userAddress, daiPoolInstance.address).call();
expect(new BN(daiBalance)).to.be.bignumber.least(ether('1000'));
});
it('should deposit 100 DAI in DAI pool', async () => {
var amountInWei = new BN(ether(100)).toString()
await daiPoolInstance.deposit(amountInWei, {from: userAddress});
const daiBalance = await daiContract.methods.balanceOf(daiPoolInstance.address).call();
expect(new BN(daiBalance)).to.be.bignumber.least(amountInWei);
var totalSupply = await poolInstance.totalSupply();
expect(new BN(totalSupply)).to.be.bignumber.least(amountInWei);
});
it('should add profit 10 DAI and calculate exchange rate', async () => {
var amountInWei = new BN(ether(10)).toString()
await daiContract.methods
.transfer(daiRateLogicInstance.address, amountInWei)
.send({ from: userAddress});
await daiPoolInstance.deposit(amountInWei, {from: userAddress});
const daiBalance = await daiContract.methods.balanceOf(daiPoolInstance.address).call();
expect(new BN(daiBalance)).to.be.bignumber.least(amountInWei);
var totalSupply = await poolInstance.totalSupply();
expect(new BN(totalSupply)).to.be.bignumber.least(amountInWei);
});
});

325
test/abi/erc20.js Normal file
View File

@ -0,0 +1,325 @@
module.exports = [
{
constant: true,
inputs: [],
name: 'name',
outputs: [{ name: '', type: 'bytes32' }],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: false,
inputs: [],
name: 'stop',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: false,
inputs: [
{ name: 'guy', type: 'address' },
{ name: 'wad', type: 'uint256' }
],
name: 'approve',
outputs: [{ name: '', type: 'bool' }],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: false,
inputs: [{ name: 'owner_', type: 'address' }],
name: 'setOwner',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'totalSupply',
outputs: [{ name: '', type: 'uint256' }],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: false,
inputs: [
{ name: 'src', type: 'address' },
{ name: 'dst', type: 'address' },
{ name: 'wad', type: 'uint256' }
],
name: 'transferFrom',
outputs: [{ name: '', type: 'bool' }],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'decimals',
outputs: [{ name: '', type: 'uint256' }],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: false,
inputs: [
{ name: 'guy', type: 'address' },
{ name: 'wad', type: 'uint256' }
],
name: 'mint',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: false,
inputs: [{ name: 'wad', type: 'uint256' }],
name: 'burn',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: false,
inputs: [{ name: 'name_', type: 'bytes32' }],
name: 'setName',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: true,
inputs: [{ name: 'src', type: 'address' }],
name: 'balanceOf',
outputs: [{ name: '', type: 'uint256' }],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'stopped',
outputs: [{ name: '', type: 'bool' }],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: false,
inputs: [{ name: 'authority_', type: 'address' }],
name: 'setAuthority',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'owner',
outputs: [{ name: '', type: 'address' }],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'symbol',
outputs: [{ name: '', type: 'bytes32' }],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: false,
inputs: [
{ name: 'guy', type: 'address' },
{ name: 'wad', type: 'uint256' }
],
name: 'burn',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: false,
inputs: [{ name: 'wad', type: 'uint256' }],
name: 'mint',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: false,
inputs: [
{ name: 'dst', type: 'address' },
{ name: 'wad', type: 'uint256' }
],
name: 'transfer',
outputs: [{ name: '', type: 'bool' }],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: false,
inputs: [
{ name: 'dst', type: 'address' },
{ name: 'wad', type: 'uint256' }
],
name: 'push',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: false,
inputs: [
{ name: 'src', type: 'address' },
{ name: 'dst', type: 'address' },
{ name: 'wad', type: 'uint256' }
],
name: 'move',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: false,
inputs: [],
name: 'start',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: true,
inputs: [],
name: 'authority',
outputs: [{ name: '', type: 'address' }],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: false,
inputs: [{ name: 'guy', type: 'address' }],
name: 'approve',
outputs: [{ name: '', type: 'bool' }],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
constant: true,
inputs: [
{ name: 'src', type: 'address' },
{ name: 'guy', type: 'address' }
],
name: 'allowance',
outputs: [{ name: '', type: 'uint256' }],
payable: false,
stateMutability: 'view',
type: 'function'
},
{
constant: false,
inputs: [
{ name: 'src', type: 'address' },
{ name: 'wad', type: 'uint256' }
],
name: 'pull',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function'
},
{
inputs: [{ name: 'symbol_', type: 'bytes32' }],
payable: false,
stateMutability: 'nonpayable',
type: 'constructor'
},
{
anonymous: false,
inputs: [
{ indexed: true, name: 'guy', type: 'address' },
{ indexed: false, name: 'wad', type: 'uint256' }
],
name: 'Mint',
type: 'event'
},
{
anonymous: false,
inputs: [
{ indexed: true, name: 'guy', type: 'address' },
{ indexed: false, name: 'wad', type: 'uint256' }
],
name: 'Burn',
type: 'event'
},
{
anonymous: false,
inputs: [{ indexed: true, name: 'authority', type: 'address' }],
name: 'LogSetAuthority',
type: 'event'
},
{
anonymous: false,
inputs: [{ indexed: true, name: 'owner', type: 'address' }],
name: 'LogSetOwner',
type: 'event'
},
{
anonymous: true,
inputs: [
{ indexed: true, name: 'sig', type: 'bytes4' },
{ indexed: true, name: 'guy', type: 'address' },
{ indexed: true, name: 'foo', type: 'bytes32' },
{ indexed: true, name: 'bar', type: 'bytes32' },
{ indexed: false, name: 'wad', type: 'uint256' },
{ indexed: false, name: 'fax', type: 'bytes' }
],
name: 'LogNote',
type: 'event'
},
{
anonymous: false,
inputs: [
{ indexed: true, name: 'src', type: 'address' },
{ indexed: true, name: 'guy', type: 'address' },
{ indexed: false, name: 'wad', type: 'uint256' }
],
name: 'Approval',
type: 'event'
},
{
anonymous: false,
inputs: [
{ indexed: true, name: 'src', type: 'address' },
{ indexed: true, name: 'dst', type: 'address' },
{ indexed: false, name: 'wad', type: 'uint256' }
],
name: 'Transfer',
type: 'event'
}
];

View File

View File

@ -42,11 +42,11 @@ module.exports = {
// tab if you use this network and you must also set the `host`, `port` and `network_id`
// options below to some value.
//
// development: {
// host: "127.0.0.1", // Localhost (default: none)
// port: 8545, // Standard Ethereum port (default: none)
// network_id: "*", // Any network (default: none)
// },
development: {
host: "127.0.0.1", // Localhost (default: none)
port: 8545, // Standard Ethereum port (default: none)
network_id: "*", // Any network (default: none)
},
// Another network with more advanced options...
// advanced: {