mirror of
https://github.com/Instadapp/yield-contract.git
synced 2024-07-29 21:47:29 +00:00
commit
80d318bcbb
1
.env.example
Normal file
1
.env.example
Normal file
|
@ -0,0 +1 @@
|
|||
INFURA_KEY=[INFURA_PROJECT_ID]
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -7,3 +7,5 @@ build/*
|
|||
|
||||
#Vim
|
||||
*.swp
|
||||
|
||||
.env
|
||||
|
|
|
@ -33,19 +33,20 @@ interface RateInterface {
|
|||
contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
event LogDeploy(address token, uint amount);
|
||||
event LogDeploy(address indexed dsa, address token, uint amount);
|
||||
event LogExchangeRate(uint exchangeRate, uint tokenBalance, uint insuranceAmt);
|
||||
event LogSettle(uint settleTime);
|
||||
event LogDeposit(uint depositAmt, uint poolMintAmt);
|
||||
event LogWithdraw(uint withdrawAmt, uint poolBurnAmt, uint feeAmt);
|
||||
event LogSettle(uint settleBlock);
|
||||
event LogDeposit(address indexed user, uint depositAmt, uint poolMintAmt);
|
||||
event LogWithdraw(address indexed user, uint withdrawAmt, uint poolBurnAmt, uint feeAmt);
|
||||
event LogAddInsurance(uint amount);
|
||||
event LogWithdrawInsurance(uint amount);
|
||||
event LogPausePool(bool);
|
||||
|
||||
IERC20 public immutable baseToken; // Base token. Eg:- DAI, USDC, etc.
|
||||
RegistryInterface public immutable registry; // Pool Registry
|
||||
IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); // Main Index
|
||||
|
||||
uint private tokenBalance; // total token balance since last rebalancing
|
||||
uint private tokenBalance; // total token balance
|
||||
uint public exchangeRate; // initial 1 token = 1
|
||||
uint public insuranceAmt; // insurance amount to keep pool safe
|
||||
|
||||
|
@ -65,44 +66,69 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable {
|
|||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Deploy assets to DSA.
|
||||
* @param _dsa DSA address
|
||||
* @param token token address
|
||||
* @param amount token amount
|
||||
*/
|
||||
function deploy(address _dsa, address token, uint amount) public isChief {
|
||||
require(registry.isDsa(address(this), _dsa), "not-autheticated-dsa");
|
||||
require(AccountInterface(_dsa).isAuth(address(this)), "token-pool-not-auth");
|
||||
if (token == address(0)) {
|
||||
if (token == address(0)) { // pool base token
|
||||
baseToken.safeTransfer(_dsa, amount);
|
||||
} else if (token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE){
|
||||
} else if (token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE){ // non-pool ethereum
|
||||
payable(_dsa).transfer(amount);
|
||||
} else {
|
||||
} else { // non-pool other tokens
|
||||
IERC20(token).safeTransfer(_dsa, amount);
|
||||
}
|
||||
emit LogDeploy(token, amount);
|
||||
emit LogDeploy(_dsa, token, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev get pool token rate
|
||||
* @param tokenAmt total token amount
|
||||
*/
|
||||
function getCurrentRate(uint tokenAmt) public view returns (uint) {
|
||||
return wdiv(totalSupply(), tokenAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev sets exchange rates
|
||||
*/
|
||||
function setExchangeRate() public isChief {
|
||||
uint _previousRate = exchangeRate;
|
||||
uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken();
|
||||
_totalToken = sub(_totalToken, insuranceAmt);
|
||||
uint _currentRate = wdiv(totalSupply(), _totalToken);
|
||||
require(_currentRate != 0, "currentRate-is-0");
|
||||
if (_currentRate > _previousRate) {
|
||||
uint difTkn = sub(tokenBalance, _totalToken);
|
||||
if (difTkn < insuranceAmt) {
|
||||
insuranceAmt = sub(insuranceAmt, difTkn);
|
||||
uint _currentRate = getCurrentRate(_totalToken);
|
||||
require(_currentRate != 0, "current-rate-is-zero");
|
||||
if (_currentRate > _previousRate) { // loss => deduct partially/fully from insurance amount
|
||||
uint _loss = sub(tokenBalance, _totalToken);
|
||||
if (_loss <= insuranceAmt) {
|
||||
insuranceAmt = sub(insuranceAmt, _loss);
|
||||
_currentRate = _previousRate;
|
||||
} else {
|
||||
tokenBalance = add(_totalToken, insuranceAmt);
|
||||
_currentRate = wdiv(totalSupply(), tokenBalance);
|
||||
insuranceAmt = 0;
|
||||
_currentRate = getCurrentRate(tokenBalance);
|
||||
}
|
||||
} else {
|
||||
} else { // profit => add to insurance amount
|
||||
uint insureFeeAmt = wmul(sub(_totalToken, tokenBalance), registry.insureFee(address(this)));
|
||||
insuranceAmt = add(insuranceAmt, insureFeeAmt);
|
||||
tokenBalance = sub(_totalToken, insureFeeAmt);
|
||||
_currentRate = wdiv(totalSupply(), tokenBalance);
|
||||
_currentRate = getCurrentRate(tokenBalance);
|
||||
}
|
||||
exchangeRate = _currentRate;
|
||||
emit LogExchangeRate(exchangeRate, tokenBalance, insuranceAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Settle the assets on dsa and update exchange rate
|
||||
* @param _dsa DSA address
|
||||
* @param _targets array of connector's address
|
||||
* @param _datas array of connector's function calldata
|
||||
* @param _origin origin address
|
||||
*/
|
||||
function settle(address _dsa, address[] calldata _targets, bytes[] calldata _datas, address _origin) external isChief {
|
||||
require(registry.isDsa(address(this), _dsa), "not-autheticated-dsa");
|
||||
AccountInterface dsaWallet = AccountInterface(_dsa);
|
||||
|
@ -110,35 +136,48 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable {
|
|||
dsaWallet.cast(_targets, _datas, _origin);
|
||||
}
|
||||
require(dsaWallet.isAuth(address(this)), "token-pool-not-auth");
|
||||
|
||||
setExchangeRate();
|
||||
emit LogSettle(block.timestamp);
|
||||
emit LogSettle(block.number);
|
||||
}
|
||||
|
||||
function deposit(uint tknAmt) external whenNotPaused payable returns(uint) {
|
||||
uint _newTokenBal = add(tokenBalance, tknAmt);
|
||||
/**
|
||||
* @dev Deposit token.
|
||||
* @param tknAmt token amount
|
||||
* @return _mintAmt amount of wrap token minted
|
||||
*/
|
||||
function deposit(uint tknAmt) external whenNotPaused payable returns (uint _mintAmt) {
|
||||
require(msg.value == 0, "non-eth-pool");
|
||||
tokenBalance = add(tokenBalance, tknAmt);
|
||||
|
||||
baseToken.safeTransferFrom(msg.sender, address(this), tknAmt);
|
||||
uint _mintAmt = wmul(tknAmt, exchangeRate);
|
||||
_mintAmt = wmul(tknAmt, exchangeRate);
|
||||
_mint(msg.sender, _mintAmt);
|
||||
|
||||
emit LogDeposit(tknAmt, _mintAmt);
|
||||
emit LogDeposit(msg.sender, tknAmt, _mintAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw tokens.
|
||||
* @param tknAmt token amount
|
||||
* @param to withdraw tokens to address
|
||||
* @return _tknAmt amount of token withdrawn
|
||||
*/
|
||||
function withdraw(uint tknAmt, address to) external nonReentrant whenNotPaused returns (uint _tknAmt) {
|
||||
uint poolBal = baseToken.balanceOf(address(this));
|
||||
require(tknAmt <= poolBal, "not-enough-liquidity-available");
|
||||
require(to != address(0), "to-address-not-vaild");
|
||||
uint _bal = balanceOf(msg.sender);
|
||||
uint _tknBal = wdiv(_bal, exchangeRate);
|
||||
uint _burnAmt;
|
||||
if (tknAmt == uint(-1)) {
|
||||
if (tknAmt >= _tknBal) {
|
||||
_burnAmt = _bal;
|
||||
_tknAmt = _tknBal;
|
||||
} else {
|
||||
require(tknAmt <= _tknBal, "balance-exceeded");
|
||||
_burnAmt = wmul(tknAmt, exchangeRate);
|
||||
_tknAmt = tknAmt;
|
||||
}
|
||||
require(_tknAmt <= poolBal, "not-enough-liquidity-available");
|
||||
|
||||
tokenBalance = sub(tokenBalance, _tknAmt);
|
||||
|
||||
_burn(msg.sender, _burnAmt);
|
||||
|
||||
|
@ -152,28 +191,36 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable {
|
|||
|
||||
baseToken.safeTransfer(to, _tknAmt);
|
||||
|
||||
emit LogWithdraw(tknAmt, _burnAmt, _feeAmt);
|
||||
emit LogWithdraw(msg.sender, _tknAmt, _burnAmt, _feeAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Add Insurance to the pool.
|
||||
* @param tknAmt insurance token amount to add
|
||||
*/
|
||||
function addInsurance(uint tknAmt) external {
|
||||
baseToken.safeTransferFrom(msg.sender, address(this), tknAmt);
|
||||
insuranceAmt = add(insuranceAmt, tknAmt);
|
||||
emit LogAddInsurance(tknAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw Insurance from the pool.
|
||||
* @notice only master can call this function.
|
||||
* @param tknAmt insurance token amount to remove
|
||||
*/
|
||||
function withdrawInsurance(uint tknAmt) external {
|
||||
require(msg.sender == instaIndex.master(), "not-master");
|
||||
require(tknAmt <= insuranceAmt || tknAmt == uint(-1), "not-enough-insurance");
|
||||
if (tknAmt == uint(-1)) {
|
||||
baseToken.safeTransfer(msg.sender, insuranceAmt);
|
||||
insuranceAmt = 0;
|
||||
} else {
|
||||
baseToken.safeTransfer(msg.sender, tknAmt);
|
||||
insuranceAmt = sub(insuranceAmt, tknAmt);
|
||||
}
|
||||
emit LogAddInsurance(tknAmt);
|
||||
require(tknAmt <= insuranceAmt, "not-enough-insurance");
|
||||
baseToken.safeTransfer(msg.sender, tknAmt);
|
||||
insuranceAmt = sub(insuranceAmt, tknAmt);
|
||||
emit LogWithdrawInsurance(tknAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Shut the pool.
|
||||
* @notice only master can call this function.
|
||||
*/
|
||||
function shutdown() external {
|
||||
require(msg.sender == instaIndex.master(), "not-master");
|
||||
paused() ? _unpause() : _pause();
|
||||
|
|
|
@ -30,22 +30,23 @@ 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);
|
||||
event LogDeploy(address indexed dsa, address indexed token, uint amount);
|
||||
event LogExchangeRate(uint exchangeRate, uint tokenBalance, uint insuranceAmt);
|
||||
event LogSettle(uint settleTime);
|
||||
event LogDeposit(uint depositAmt, uint poolMintAmt);
|
||||
event LogWithdraw(uint withdrawAmt, uint poolBurnAmt, uint feeAmt);
|
||||
event LogSettle(uint settleBlock);
|
||||
event LogDeposit(address indexed user, uint depositAmt, uint poolMintAmt);
|
||||
event LogWithdraw(address indexed user, uint withdrawAmt, uint poolBurnAmt, uint feeAmt);
|
||||
event LogAddInsurance(uint amount);
|
||||
event LogWithdrawInsurance(uint amount);
|
||||
event LogPausePool(bool);
|
||||
|
||||
RegistryInterface public immutable registry; // Pool Registry
|
||||
IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723);
|
||||
|
||||
IERC20 public immutable baseToken; // Base token.
|
||||
uint private tokenBalance; // total token balance since last rebalancing
|
||||
uint private tokenBalance; // total token balance
|
||||
uint public exchangeRate = 10 ** 18; // initial 1 token = 1
|
||||
uint public insuranceAmt; // insurance amount to keep pool safe
|
||||
|
||||
|
@ -64,78 +65,115 @@ contract PoolToken is ReentrancyGuard, ERC20Pausable, DSMath {
|
|||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Deploy assets to DSA.
|
||||
* @param _dsa DSA address
|
||||
* @param token token address
|
||||
* @param amount token amount
|
||||
*/
|
||||
function deploy(address _dsa, address token, uint amount) external isChief {
|
||||
require(registry.isDsa(address(this), _dsa), "not-autheticated-dsa");
|
||||
require(AccountInterface(_dsa).isAuth(address(this)), "token-pool-not-auth");
|
||||
if (token == address(0)) {
|
||||
require(AccountInterface(_dsa).isAuth(address(this)), "token-pool-not-auth");
|
||||
if (token == address(0)) { // pool base ETH
|
||||
payable(_dsa).transfer(amount);
|
||||
} else {
|
||||
} else { // non-pool other tokens
|
||||
IERC20(token).safeTransfer(_dsa, amount);
|
||||
}
|
||||
emit LogDeploy(token, amount);
|
||||
emit LogDeploy(_dsa, token, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev get pool token rate
|
||||
* @param tokenAmt total token amount
|
||||
*/
|
||||
function getCurrentRate(uint tokenAmt) public view returns (uint) {
|
||||
return wdiv(totalSupply(), tokenAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev sets exchange rates
|
||||
*/
|
||||
function setExchangeRate() public isChief {
|
||||
uint _previousRate = exchangeRate;
|
||||
uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken();
|
||||
_totalToken = sub(_totalToken, insuranceAmt);
|
||||
uint _currentRate = wdiv(totalSupply(), _totalToken);
|
||||
require(_currentRate != 0, "currentRate-is-0");
|
||||
if (_currentRate > _previousRate) {
|
||||
uint difTkn = sub(tokenBalance, _totalToken);
|
||||
if (difTkn < insuranceAmt) {
|
||||
insuranceAmt = sub(insuranceAmt, difTkn);
|
||||
uint _currentRate = getCurrentRate(_totalToken);
|
||||
require(_currentRate != 0, "current-rate-is-zero");
|
||||
if (_currentRate > _previousRate) { // loss => deduct partially/fully from insurance amount
|
||||
uint _loss = sub(tokenBalance, _totalToken);
|
||||
if (_loss <= insuranceAmt) {
|
||||
insuranceAmt = sub(insuranceAmt, _loss);
|
||||
_currentRate = _previousRate;
|
||||
} else {
|
||||
tokenBalance = add(_totalToken, insuranceAmt);
|
||||
_currentRate = wdiv(totalSupply(), tokenBalance);
|
||||
insuranceAmt = 0;
|
||||
_currentRate = getCurrentRate(tokenBalance);
|
||||
}
|
||||
} else {
|
||||
} else { // profit => add to insurance amount
|
||||
uint insureFeeAmt = wmul(sub(_totalToken, tokenBalance), registry.insureFee(address(this)));
|
||||
insuranceAmt = add(insuranceAmt, insureFeeAmt);
|
||||
tokenBalance = sub(_totalToken, insureFeeAmt);
|
||||
_currentRate = wdiv(totalSupply(), tokenBalance);
|
||||
_currentRate = getCurrentRate(tokenBalance);
|
||||
}
|
||||
exchangeRate = _currentRate;
|
||||
emit LogExchangeRate(exchangeRate, tokenBalance, insuranceAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Settle the assets on dsa and update exchange rate
|
||||
* @param _dsa DSA address
|
||||
* @param _targets array of connector's address
|
||||
* @param _datas array of connector's function calldata
|
||||
* @param _origin origin address
|
||||
*/
|
||||
function settle(address _dsa, address[] calldata _targets, bytes[] calldata _datas, address _origin) external isChief {
|
||||
require(registry.isDsa(address(this), _dsa), "not-autheticated-dsa");
|
||||
AccountInterface dsaWallet = AccountInterface(_dsa);
|
||||
if (_targets.length > 0 && _datas.length > 0) {
|
||||
dsaWallet.cast(_targets, _datas, _origin);
|
||||
}
|
||||
require(dsaWallet.isAuth(address(this)), "token-pool-not-auth");
|
||||
require(dsaWallet.isAuth(address(this)), "token-pool-not-auth");
|
||||
setExchangeRate();
|
||||
|
||||
emit LogSettle(block.timestamp);
|
||||
emit LogSettle(block.number);
|
||||
}
|
||||
|
||||
function deposit(uint tknAmt) public whenNotPaused payable returns(uint) {
|
||||
/**
|
||||
* @dev Deposit token.
|
||||
* @param tknAmt token amount
|
||||
* @return _mintAmt amount of wrap token minted
|
||||
*/
|
||||
function deposit(uint tknAmt) public whenNotPaused payable returns (uint _mintAmt) {
|
||||
require(tknAmt == msg.value, "unmatched-amount");
|
||||
uint _newTokenBal = add(tokenBalance, msg.value);
|
||||
tokenBalance = add(tokenBalance, tknAmt);
|
||||
|
||||
uint _mintAmt = wmul(msg.value, exchangeRate);
|
||||
_mintAmt = wmul(msg.value, exchangeRate);
|
||||
_mint(msg.sender, _mintAmt);
|
||||
|
||||
emit LogDeposit(tknAmt, _mintAmt);
|
||||
emit LogDeposit(msg.sender, tknAmt, _mintAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw tokens.
|
||||
* @param tknAmt token amount
|
||||
* @param to withdraw tokens to address
|
||||
* @return _tknAmt amount of token withdrawn
|
||||
*/
|
||||
function withdraw(uint tknAmt, address to) external nonReentrant whenNotPaused returns (uint _tknAmt) {
|
||||
uint poolBal = address(this).balance;
|
||||
require(tknAmt <= poolBal, "not-enough-liquidity-available");
|
||||
require(to != address(0), "to-address-not-vaild");
|
||||
uint _bal = balanceOf(msg.sender);
|
||||
uint _tknBal = wdiv(_bal, exchangeRate);
|
||||
uint _burnAmt;
|
||||
if (tknAmt == uint(-1)) {
|
||||
if (tknAmt >= _tknBal) {
|
||||
_burnAmt = _bal;
|
||||
_tknAmt = _tknBal;
|
||||
} else {
|
||||
require(tknAmt <= _tknBal, "balance-exceeded");
|
||||
_burnAmt = wmul(tknAmt, exchangeRate);
|
||||
_tknAmt = tknAmt;
|
||||
}
|
||||
require(_tknAmt <= poolBal, "not-enough-liquidity-available");
|
||||
|
||||
tokenBalance = sub(tokenBalance, _tknAmt);
|
||||
|
||||
_burn(msg.sender, _burnAmt);
|
||||
|
||||
|
@ -149,33 +187,40 @@ contract PoolToken is ReentrancyGuard, ERC20Pausable, DSMath {
|
|||
|
||||
payable(to).transfer(_tknAmt);
|
||||
|
||||
emit LogWithdraw(tknAmt, _burnAmt, _feeAmt);
|
||||
emit LogWithdraw(msg.sender, _tknAmt, _burnAmt, _feeAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Add Insurance to the pool.
|
||||
* @param tknAmt insurance token amount to add
|
||||
*/
|
||||
function addInsurance(uint tknAmt) external payable {
|
||||
require(tknAmt == msg.value, "unmatched-amount");
|
||||
insuranceAmt += tknAmt;
|
||||
insuranceAmt = add(insuranceAmt, tknAmt);
|
||||
emit LogAddInsurance(tknAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw Insurance from the pool.
|
||||
* @notice only master can call this function.
|
||||
* @param tknAmt insurance token amount to remove
|
||||
*/
|
||||
function withdrawInsurance(uint tknAmt) external {
|
||||
require(msg.sender == instaIndex.master(), "not-master");
|
||||
require(tknAmt <= insuranceAmt || tknAmt == uint(-1), "not-enough-insurance");
|
||||
if (tknAmt == uint(-1)) {
|
||||
msg.sender.transfer(insuranceAmt);
|
||||
insuranceAmt = 0;
|
||||
} else {
|
||||
msg.sender.transfer(tknAmt);
|
||||
insuranceAmt = sub(insuranceAmt, tknAmt);
|
||||
}
|
||||
emit LogAddInsurance(tknAmt);
|
||||
require(tknAmt <= insuranceAmt, "not-enough-insurance");
|
||||
msg.sender.transfer(tknAmt);
|
||||
insuranceAmt = sub(insuranceAmt, tknAmt);
|
||||
emit LogWithdrawInsurance(tknAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Shut the pool.
|
||||
* @notice only master can call this function.
|
||||
*/
|
||||
function shutdown() external {
|
||||
require(msg.sender == instaIndex.master(), "not-master");
|
||||
paused() ? _unpause() : _pause();
|
||||
}
|
||||
|
||||
receive() external payable {}
|
||||
|
||||
}
|
||||
|
|
|
@ -127,6 +127,11 @@ contract Registry {
|
|||
emit LogUpdatePool(_pool, isPool[_pool]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev update pool rate logic
|
||||
* @param _pool pool address
|
||||
* @param _newLogic new rate logic address
|
||||
*/
|
||||
function updatePoolLogic(address _pool, address _newLogic) external isMaster {
|
||||
require(isPool[_pool], "not-pool");
|
||||
require(_newLogic != address(0), "invalid-address");
|
||||
|
@ -135,6 +140,11 @@ contract Registry {
|
|||
emit LogUpdatePoolLogic(_pool, _newLogic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev update pool insure fee
|
||||
* @param _pool pool address
|
||||
* @param _newFee new fee amount
|
||||
*/
|
||||
function updateInsureFee(address _pool, uint _newFee) external isMaster {
|
||||
require(isPool[_pool], "not-pool");
|
||||
require(_newFee < 10 ** 18, "insure-fee-limit-reached");
|
||||
|
@ -143,6 +153,11 @@ contract Registry {
|
|||
emit LogUpdateInsureFee(_pool, _newFee);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev update pool withdrawal fee
|
||||
* @param _pool pool address
|
||||
* @param _newFee new withdrawal fee amount
|
||||
*/
|
||||
function updateWithdrawalFee(address _pool, uint _newFee) external isMaster {
|
||||
require(isPool[_pool], "not-pool");
|
||||
require(_newFee < 1 * 10 ** 16, "withdrawal-fee-limit-reached");
|
||||
|
@ -151,6 +166,11 @@ contract Registry {
|
|||
emit LogUpdateWithdrawalFee(_pool, _newFee);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev add dsa for a pool
|
||||
* @param _pool pool address
|
||||
* @param _dsa DSA address
|
||||
*/
|
||||
function addDsa(address _pool, address _dsa) external isMaster {
|
||||
require(isPool[_pool], "not-pool");
|
||||
if (_dsa == address(0)) _dsa = instaIndex.build(_pool, 1, address(this));
|
||||
|
@ -159,6 +179,11 @@ contract Registry {
|
|||
emit LogNewDSA(_pool, _dsa);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev remove dsa from a pool
|
||||
* @param _pool pool address
|
||||
* @param _dsa DSA address
|
||||
*/
|
||||
function removeDsa(address _pool, address _dsa) external isMaster {
|
||||
require(isPool[_pool], "not-pool");
|
||||
require(isDsa[_pool][_dsa], "not-dsa-for-pool");
|
||||
|
|
28
contracts/tests/daiLogic.sol
Normal file
28
contracts/tests/daiLogic.sol
Normal 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));
|
||||
}
|
||||
}
|
22
contracts/tests/ethLogic.sol
Normal file
22
contracts/tests/ethLogic.sol
Normal file
|
@ -0,0 +1,22 @@
|
|||
// 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);
|
||||
}
|
||||
|
||||
receive() external payable {}
|
||||
}
|
4
migrations/2_registry.js
Normal file
4
migrations/2_registry.js
Normal 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
10
migrations/3_erc20Pool.js
Normal 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
11
migrations/4_ethPool.js
Normal 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
11372
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -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
5
scripts/utils.js
Normal 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
122
test/1_registry.js
Normal 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);
|
||||
}
|
164
test/2_daiPool.js
Normal file
164
test/2_daiPool.js
Normal file
|
@ -0,0 +1,164 @@
|
|||
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 send ether to the master address', async () => {
|
||||
// Send 1 eth to userAddress to have gas to send an ERC20 tx.
|
||||
await web3.eth.sendTransaction({
|
||||
from: accounts[0],
|
||||
to: masterAddr,
|
||||
value: ether('1')
|
||||
});
|
||||
const ethBalance = await balance.current(masterAddr);
|
||||
expect(new BN(ethBalance)).to.be.bignumber.least(new BN(ether('1')));
|
||||
});
|
||||
|
||||
it('should send DAI to the account[0] address', async () => {
|
||||
await daiContract.methods
|
||||
.transfer(accounts[0], ether('1000').toString())
|
||||
.send({ from: userAddress});
|
||||
const daiBalance = await daiContract.methods.balanceOf(accounts[0]).call();
|
||||
expect(new BN(daiBalance)).to.be.bignumber.least(ether('1000'));
|
||||
});
|
||||
|
||||
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 DAI Logic contract in registry', async () => {
|
||||
await updateRateLogic(registryInstance, daiPoolInstance.address, daiRateLogicInstance.address);
|
||||
});
|
||||
|
||||
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 = (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 daiPoolInstance.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});
|
||||
var exchangeRateInit = await daiPoolInstance.exchangeRate()
|
||||
await daiPoolInstance.setExchangeRate({from: masterAddr});
|
||||
var exchangeRateFinal = await daiPoolInstance.exchangeRate()
|
||||
expect(exchangeRateInit).to.not.equal(exchangeRateFinal);
|
||||
});
|
||||
|
||||
it('should give DAI allowance for DAI pool(accounts[0])', async () => {
|
||||
await daiContract.methods
|
||||
.approve(daiPoolInstance.address, ether('1000').toString())
|
||||
.send({ from: accounts[0]});
|
||||
const daiBalance = await daiContract.methods.allowance(accounts[0], daiPoolInstance.address).call();
|
||||
expect(new BN(daiBalance)).to.be.bignumber.least(ether('1000'));
|
||||
});
|
||||
|
||||
it('should deposit 100 DAI in DAI pool(accounts[0])', async () => {
|
||||
var amountInWei = (ether("100")).toString()
|
||||
await daiPoolInstance.deposit(amountInWei, {from: accounts[0]});
|
||||
const wrapDaiBalance = await daiPoolInstance.balanceOf(accounts[0])
|
||||
expect(new BN(wrapDaiBalance)).to.be.bignumber.least((ether("90")).toString());
|
||||
});
|
||||
|
||||
it('should withdraw 10 DAI in DAI pool', async () => {
|
||||
var amountInWei = (ether("10")).toString()
|
||||
await daiPoolInstance.withdraw(amountInWei, accounts[1], {from: userAddress});
|
||||
const daiBalance = await daiContract.methods.balanceOf(accounts[1]).call();
|
||||
expect(new BN(daiBalance)).to.be.bignumber.least(amountInWei);
|
||||
});
|
||||
|
||||
it('should withdraw total DAI in DAI pool', async () => {
|
||||
var amountInWei = (ether("1000")).toString()
|
||||
var checkAmt = (ether("90")).toString()
|
||||
await daiPoolInstance.withdraw(amountInWei, accounts[2], {from: userAddress});
|
||||
const daiBalance = await daiContract.methods.balanceOf(accounts[2]).call();
|
||||
expect(new BN(daiBalance)).to.be.bignumber.least(checkAmt);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
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 enablePool(registryInstance, poolAddr) {
|
||||
await registryInstance.updatePool(poolAddr, {from: masterAddr});
|
||||
|
||||
var _isPool = await registryInstance.isPool(poolAddr);
|
||||
expect(_isPool).to.equal(true);
|
||||
}
|
||||
|
||||
async function updateRateLogic(registryInstance, poolAddr, logicAddr) {
|
||||
await registryInstance.updatePoolLogic(poolAddr, logicAddr, {from: masterAddr});
|
||||
|
||||
var _logicAddr = await registryInstance.poolLogic(poolAddr);
|
||||
expect(_logicAddr).to.equal(logicAddr);
|
||||
}
|
119
test/3_ethPool.js
Normal file
119
test/3_ethPool.js
Normal file
|
@ -0,0 +1,119 @@
|
|||
const { BN, ether, balance } = require('@openzeppelin/test-helpers');
|
||||
const { expect } = require('chai');
|
||||
|
||||
const RegistryContract = artifacts.require("Registry");
|
||||
const PoolETHContract = artifacts.require("PoolETH");
|
||||
|
||||
const EthRateLogic = artifacts.require("EthRateLogic");
|
||||
|
||||
|
||||
const masterAddr = "0xfCD22438AD6eD564a1C26151Df73F6B33B817B56"
|
||||
|
||||
// ABI
|
||||
|
||||
contract('ETH Pool', async accounts => {
|
||||
let ethAddr = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
||||
|
||||
let accountA = accounts[0];
|
||||
let accountB = accounts[1];
|
||||
|
||||
let ethPoolInstance;
|
||||
let registryInstance;
|
||||
|
||||
let ethRateLogicInstance;
|
||||
before(async() => {
|
||||
registryInstance = await RegistryContract.deployed();
|
||||
ethPoolInstance = await PoolETHContract.deployed();
|
||||
|
||||
ethRateLogicInstance = await EthRateLogic.deployed();
|
||||
})
|
||||
|
||||
it('should send ether to the master address', async () => {
|
||||
// Send 1 eth to userAddress to have gas to send an ERC20 tx.
|
||||
await web3.eth.sendTransaction({
|
||||
from: accounts[0],
|
||||
to: masterAddr,
|
||||
value: ether('1')
|
||||
});
|
||||
const ethBalance = await balance.current(masterAddr);
|
||||
expect(new BN(ethBalance)).to.be.bignumber.least(new BN(ether('1')));
|
||||
});
|
||||
|
||||
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 update ETH Logic contract in registry', async () => {
|
||||
await updateRateLogic(registryInstance, ethPoolInstance.address, ethRateLogicInstance.address);
|
||||
});
|
||||
|
||||
it('should deposit 5 ETH in ETH pool', async () => {
|
||||
var amountInWei = (ether("5")).toString()
|
||||
await ethPoolInstance.deposit(amountInWei, {from: accountA, value: amountInWei});
|
||||
const ethBalance = await web3.eth.getBalance(ethPoolInstance.address);
|
||||
expect(new BN(ethBalance)).to.be.bignumber.least(amountInWei);
|
||||
var totalSupply = await ethPoolInstance.totalSupply();
|
||||
expect(new BN(totalSupply)).to.be.bignumber.least(amountInWei);
|
||||
});
|
||||
|
||||
it('should add profit 0.5 ETH and calculate exchange rate', async () => {
|
||||
var amountInWei = new BN(ether("0.5")).toString()
|
||||
await web3.eth.sendTransaction({
|
||||
from: accountA,
|
||||
to: ethRateLogicInstance.address,
|
||||
value: amountInWei
|
||||
});
|
||||
var exchangeRateInit = await ethPoolInstance.exchangeRate()
|
||||
await ethPoolInstance.setExchangeRate({from: masterAddr});
|
||||
var exchangeRateFinal = await ethPoolInstance.exchangeRate()
|
||||
expect(exchangeRateInit).to.not.equal(exchangeRateFinal);
|
||||
});
|
||||
|
||||
it('should deposit 5 ETH in ETH pool(accountB)', async () => {
|
||||
var amountInWei = (ether("5")).toString()
|
||||
await ethPoolInstance.deposit(amountInWei, {from: accountB, value: amountInWei});
|
||||
const wrapETHBalance = await ethPoolInstance.balanceOf(accountB)
|
||||
expect(new BN(wrapETHBalance)).to.be.bignumber.least((ether("4")).toString());
|
||||
});
|
||||
|
||||
it('should withdraw 0.5 ETH in ETH pool', async () => {
|
||||
var amountInWei = (ether("0.5")).toString()
|
||||
await ethPoolInstance.withdraw(amountInWei, accounts[2], {from: accountA});
|
||||
const ethBalance = await web3.eth.getBalance(accounts[2]);
|
||||
expect(new BN(ethBalance)).to.be.bignumber.least(amountInWei);
|
||||
});
|
||||
|
||||
it('should withdraw total ETH in ETH pool', async () => {
|
||||
var amountInWei = (ether("1000")).toString()
|
||||
var checkAmt = (ether("4.5")).toString()
|
||||
await ethPoolInstance.withdraw(amountInWei, accounts[3], {from: accountA});
|
||||
const ethBalance = await web3.eth.getBalance(accounts[3]);
|
||||
expect(new BN(ethBalance)).to.be.bignumber.least(checkAmt);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
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 enablePool(registryInstance, poolAddr) {
|
||||
await registryInstance.updatePool(poolAddr, {from: masterAddr});
|
||||
|
||||
var _isPool = await registryInstance.isPool(poolAddr);
|
||||
expect(_isPool).to.equal(true);
|
||||
}
|
||||
|
||||
async function updateRateLogic(registryInstance, poolAddr, logicAddr) {
|
||||
await registryInstance.updatePoolLogic(poolAddr, logicAddr, {from: masterAddr});
|
||||
|
||||
var _logicAddr = await registryInstance.poolLogic(poolAddr);
|
||||
expect(_logicAddr).to.equal(logicAddr);
|
||||
}
|
325
test/abi/erc20.js
Normal file
325
test/abi/erc20.js
Normal 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'
|
||||
}
|
||||
];
|
|
@ -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: {
|
||||
|
|
Loading…
Reference in New Issue
Block a user