diff --git a/contracts/deployer.sol b/contracts/deployer.sol index 56df2ff..b4c0add 100644 --- a/contracts/deployer.sol +++ b/contracts/deployer.sol @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.6.8; interface IProxy { @@ -64,4 +65,4 @@ contract Deployer { bytes15 c = bytes15(0x5af43d82803e903d91602b57fd5bf3); return abi.encodePacked(a, b, c); } -} \ No newline at end of file +} diff --git a/contracts/ethPool.sol b/contracts/ethPool.sol index 771b841..2b7ae07 100644 --- a/contracts/ethPool.sol +++ b/contracts/ethPool.sol @@ -2,13 +2,12 @@ pragma solidity ^0.6.8; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol"; +import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import { DSMath } from "./libs/safeMath.sol"; -// TODO - Add ReentrancyGuard lib - interface AccountInterface { function enable(address authority) external; function cast(address[] calldata _targets, bytes[] calldata _datas, address _origin) external payable; @@ -30,126 +29,121 @@ interface RateInterface { function getTotalToken() external returns (uint totalUnderlyingTkn); } -contract PoolToken is ERC20, DSMath { - event LogDeploy(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); - event LogAddInsurance(uint amount); - event LogPausePool(bool); +contract PoolToken is ReentrancyGuard, ERC20Pausable, DSMath { + event LogDeploy(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); + event LogAddInsurance(uint amount); + event LogPausePool(bool); - // IERC20 public immutable baseToken; - RegistryInterface public immutable registry; // Pool Registry - IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); - AccountInterface public immutable dsa; // Pool's DSA account + RegistryInterface public immutable registry; // Pool Registry + IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); + AccountInterface public immutable dsa; // Pool's DSA account - IERC20 public immutable baseToken; // Base token. Eg:- DAI, USDC, etc. - uint private tokenBalance; // total token balance since last rebalancing - uint public exchangeRate = 10 ** 18; // initial 1 token = 1 - uint public insuranceAmt; // insurance amount to keep pool safe - bool public pausePool; // shutdown deposits and withdrawals + IERC20 public immutable baseToken; // Base token. + uint private tokenBalance; // total token balance since last rebalancing + uint public exchangeRate = 10 ** 18; // initial 1 token = 1 + uint public insuranceAmt; // insurance amount to keep pool safe - constructor( - address _registry, - string memory _name, - string memory _symbol, - address _baseToken, - address _origin - ) public ERC20(_name, _symbol) { - baseToken = IERC20(_baseToken); - registry = RegistryInterface(_registry); - address _dsa = instaIndex.build(address(this), 1, _origin); - dsa = AccountInterface(_dsa); + constructor( + address _registry, + string memory _name, + string memory _symbol, + address _baseToken, + address _origin + ) public ERC20(_name, _symbol) { + baseToken = IERC20(_baseToken); + registry = RegistryInterface(_registry); + address _dsa = instaIndex.build(address(this), 1, _origin); + dsa = AccountInterface(_dsa); + } + + modifier isChief() { + require(registry.chief(msg.sender) || msg.sender == instaIndex.master(), "not-chief"); + _; + } + + function deploy(uint amount) external isChief { + payable(address(dsa)).transfer(amount); + emit LogDeploy(amount); + } + + function setExchangeRate() public isChief { + uint _previousRate = exchangeRate; + uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); + uint _currentRate = wdiv(_totalToken, totalSupply()); + if (_currentRate < _previousRate) { + uint difRate = _previousRate - _currentRate; + uint difTkn = wmul(_totalToken, difRate); + insuranceAmt = sub(insuranceAmt, difTkn); + _currentRate = _previousRate; + } else { + uint difRate = _currentRate - _previousRate; + uint insureFee = wmul(difRate, registry.insureFee(address(this))); + uint insureFeeAmt = wmul(_totalToken, insureFee); + insuranceAmt = add(insuranceAmt, insureFeeAmt); + _currentRate = sub(_currentRate, insureFee); + tokenBalance = sub(_totalToken, insuranceAmt); + } + exchangeRate = _currentRate; + emit LogExchangeRate(exchangeRate, tokenBalance, insuranceAmt); + } + + function settle(address[] calldata _targets, bytes[] calldata _datas, address _origin) external isChief { + if (_targets.length > 0 && _datas.length > 0) { + dsa.cast(_targets, _datas, _origin); + } + setExchangeRate(); + + emit LogSettle(block.timestamp); + } + + function deposit(uint tknAmt) public whenNotPaused payable returns(uint) { + require(tknAmt == msg.value, "unmatched-amount"); + uint _newTokenBal = add(tokenBalance, msg.value); + require(_newTokenBal <= registry.poolCap(address(this)), "deposit-cap-reached"); + + uint _mintAmt = wdiv(msg.value, exchangeRate); + _mint(msg.sender, _mintAmt); + + emit LogDeposit(tknAmt, _mintAmt); + } + + function withdraw(uint tknAmt, address to) external nonReentrant whenNotPaused returns (uint _tknAmt) { + uint poolBal = address(this).balance; + require(tknAmt <= poolBal, "not-enough-liquidity-available"); + uint _bal = balanceOf(msg.sender); + uint _tknBal = wmul(_bal, exchangeRate); + uint _burnAmt; + if (tknAmt == uint(-1)) { + _burnAmt = _bal; + _tknAmt = wmul(_burnAmt, exchangeRate); + } else { + require(tknAmt <= _tknBal, "balance-exceeded"); + _burnAmt = wdiv(tknAmt, exchangeRate); + _tknAmt = tknAmt; } - modifier isChief() { - require(registry.chief(msg.sender) || msg.sender == instaIndex.master(), "not-chief"); - _; - } + _burn(msg.sender, _burnAmt); - function deploy(uint amount) external isChief { - payable(address(dsa)).transfer(amount); - emit LogDeploy(amount); - } + payable(to).transfer(_tknAmt); - function setExchangeRate() public isChief { - uint _previousRate = exchangeRate; - uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); - uint _currentRate = wdiv(_totalToken, totalSupply()); - if (_currentRate < _previousRate) { - uint difRate = _previousRate - _currentRate; - uint difTkn = wmul(_totalToken, difRate); - insuranceAmt = sub(insuranceAmt, difTkn); - _currentRate = _previousRate; - } else { - uint difRate = _currentRate - _previousRate; - uint insureFee = wmul(difRate, registry.insureFee(address(this))); - uint insureFeeAmt = wmul(_totalToken, insureFee); - insuranceAmt = add(insuranceAmt, insureFeeAmt); - _currentRate = sub(_currentRate, insureFee); - tokenBalance = sub(_totalToken, insuranceAmt); - } - exchangeRate = _currentRate; - emit LogExchangeRate(exchangeRate, tokenBalance, insuranceAmt); - } + emit LogWithdraw(tknAmt, _burnAmt); + } - function settle(address[] calldata _targets, bytes[] calldata _datas, address _origin) external isChief { - if (_targets.length > 0 && _datas.length > 0) { - dsa.cast(_targets, _datas, _origin); - } - setExchangeRate(); + function addInsurance(uint tknAmt) external payable { + require(tknAmt == msg.value, "unmatched-amount"); + insuranceAmt += tknAmt; + emit LogAddInsurance(tknAmt); + } - emit LogSettle(block.timestamp); - } + function shutdown() external { + require(msg.sender == instaIndex.master(), "not-master"); + paused() ? _unpause() : _pause(); + } - function deposit(uint tknAmt) public payable returns(uint) { - require(!pausePool, "pool-shut"); - require(tknAmt == msg.value, "unmatched-amount"); - uint _newTokenBal = add(tokenBalance, msg.value); - require(_newTokenBal <= registry.poolCap(address(this)), "deposit-cap-reached"); - - uint _mintAmt = wdiv(msg.value, exchangeRate); - _mint(msg.sender, _mintAmt); - - emit LogDeposit(tknAmt, _mintAmt); - } - - function withdraw(uint tknAmt, address to) external returns (uint _tknAmt) { - require(!pausePool, "pool-shut"); - uint poolBal = address(this).balance; - require(tknAmt <= poolBal, "not-enough-liquidity-available"); - uint _bal = balanceOf(msg.sender); - uint _tknBal = wmul(_bal, exchangeRate); - uint _burnAmt; - if (tknAmt == uint(-1)) { - _burnAmt = _bal; - _tknAmt = wmul(_burnAmt, exchangeRate); - } else { - require(tknAmt <= _tknBal, "balance-exceeded"); - _burnAmt = wdiv(tknAmt, exchangeRate); - _tknAmt = tknAmt; - } - - _burn(msg.sender, _burnAmt); - - payable(to).transfer(_tknAmt); // TODO - if this is also Reentrancy prone attack or not. - - emit LogWithdraw(tknAmt, _burnAmt); - } - - function addInsurance(uint tknAmt) external payable { - require(tknAmt == msg.value, "unmatched-amount"); - insuranceAmt += tknAmt; - emit LogAddInsurance(tknAmt); - } - - function shutdown() external { - require(msg.sender == instaIndex.master(), "not-master"); - pausePool = !pausePool; - emit LogPausePool(pausePool); - } - - receive() external payable {} + receive() external payable {} } diff --git a/contracts/flusher.sol b/contracts/flusher.sol index a53bbed..26152d0 100644 --- a/contracts/flusher.sol +++ b/contracts/flusher.sol @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.6.8; pragma experimental ABIEncoderV2; @@ -155,4 +156,4 @@ contract Flusher { receive() external payable {} -} \ No newline at end of file +} diff --git a/contracts/tokenPool.sol b/contracts/tokenPool.sol index bf91164..7398579 100644 --- a/contracts/tokenPool.sol +++ b/contracts/tokenPool.sol @@ -2,9 +2,9 @@ pragma solidity ^0.6.8; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol"; +import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import { DSMath } from "./libs/safeMath.sol"; @@ -29,7 +29,7 @@ interface RateInterface { function getTotalToken() external returns (uint totalUnderlyingTkn); } -contract PoolToken is DSMath, ERC20, ERC20Pausable { +contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { using SafeERC20 for IERC20; event LogDeploy(uint amount); @@ -48,7 +48,6 @@ contract PoolToken is DSMath, ERC20, ERC20Pausable { uint private tokenBalance; // total token balance since last rebalancing uint public exchangeRate = 10 ** 18; // initial 1 token = 1 uint public insuranceAmt; // insurance amount to keep pool safe - bool public pausePool; // shutdown deposits and withdrawals constructor( address _registry, @@ -69,82 +68,80 @@ contract PoolToken is DSMath, ERC20, ERC20Pausable { } function deploy(uint amount) public isChief { - baseToken.safeTransfer(address(dsa), amount); - emit LogDeploy(amount); + baseToken.safeTransfer(address(dsa), amount); + emit LogDeploy(amount); } function setExchangeRate() public isChief { - uint _previousRate = exchangeRate; - uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); - uint _currentRate = wdiv(_totalToken, totalSupply()); - if (_currentRate < _previousRate) { - uint difRate = _previousRate - _currentRate; - uint difTkn = wmul(_totalToken, difRate); - insuranceAmt = sub(insuranceAmt, difTkn); - _currentRate = _previousRate; - } else { - uint difRate = _currentRate - _previousRate; - uint insureFee = wmul(difRate, registry.insureFee(address(this))); - uint insureFeeAmt = wmul(_totalToken, insureFee); - insuranceAmt = add(insuranceAmt, insureFeeAmt); - _currentRate = sub(_currentRate, insureFee); - tokenBalance = sub(_totalToken, insuranceAmt); - } - exchangeRate = _currentRate; - emit LogExchangeRate(exchangeRate, tokenBalance, insuranceAmt); + uint _previousRate = exchangeRate; + uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); + uint _currentRate = wdiv(_totalToken, totalSupply()); + if (_currentRate < _previousRate) { + uint difRate = _previousRate - _currentRate; + uint difTkn = wmul(_totalToken, difRate); + insuranceAmt = sub(insuranceAmt, difTkn); + _currentRate = _previousRate; + } else { + uint difRate = _currentRate - _previousRate; + uint insureFee = wmul(difRate, registry.insureFee(address(this))); + uint insureFeeAmt = wmul(_totalToken, insureFee); + insuranceAmt = add(insuranceAmt, insureFeeAmt); + _currentRate = sub(_currentRate, insureFee); + tokenBalance = sub(_totalToken, insuranceAmt); + } + exchangeRate = _currentRate; + emit LogExchangeRate(exchangeRate, tokenBalance, insuranceAmt); } function settle(address[] calldata _targets, bytes[] calldata _datas, address _origin) external isChief { - if (_targets.length > 0 && _datas.length > 0) { - dsa.cast(_targets, _datas, _origin); - } - setExchangeRate(); - emit LogSettle(block.timestamp); + if (_targets.length > 0 && _datas.length > 0) { + dsa.cast(_targets, _datas, _origin); + } + setExchangeRate(); + emit LogSettle(block.timestamp); } - function deposit(uint tknAmt) external payable returns(uint) { - require(!pausePool, "pool-shut"); - uint _newTokenBal = add(tokenBalance, tknAmt); - require(_newTokenBal <= registry.poolCap(address(this)), "deposit-cap-reached"); + function deposit(uint tknAmt) external whenNotPaused payable returns(uint) { + uint _newTokenBal = add(tokenBalance, tknAmt); + require(_newTokenBal <= registry.poolCap(address(this)), "deposit-cap-reached"); - baseToken.safeTransferFrom(msg.sender, address(this), tknAmt); - uint _mintAmt = wdiv(tknAmt, exchangeRate); - _mint(msg.sender, _mintAmt); + baseToken.safeTransferFrom(msg.sender, address(this), tknAmt); + uint _mintAmt = wdiv(tknAmt, exchangeRate); + _mint(msg.sender, _mintAmt); - emit LogDeposit(tknAmt, _mintAmt); + emit LogDeposit(tknAmt, _mintAmt); } - function withdraw(uint tknAmt, address to) external returns (uint _tknAmt) { - require(!pausePool, "pool-shut"); - uint poolBal = baseToken.balanceOf(address(this)); - require(tknAmt <= poolBal, "not-enough-liquidity-available"); - uint _bal = balanceOf(msg.sender); - uint _tknBal = wmul(_bal, exchangeRate); - uint _burnAmt; - if (tknAmt == uint(-1)) { - _burnAmt = _bal; - _tknAmt = wmul(_burnAmt, exchangeRate); - } else { - require(tknAmt <= _tknBal, "balance-exceeded"); - _burnAmt = wdiv(tknAmt, exchangeRate); - _tknAmt = tknAmt; - } + 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"); + uint _bal = balanceOf(msg.sender); + uint _tknBal = wmul(_bal, exchangeRate); + uint _burnAmt; + if (tknAmt == uint(-1)) { + _burnAmt = _bal; + _tknAmt = wmul(_burnAmt, exchangeRate); + } else { + require(tknAmt <= _tknBal, "balance-exceeded"); + _burnAmt = wdiv(tknAmt, exchangeRate); + _tknAmt = tknAmt; + } - _burn(msg.sender, _burnAmt); + _burn(msg.sender, _burnAmt); - baseToken.safeTransfer(to, _tknAmt); + baseToken.safeTransfer(to, _tknAmt); - emit LogWithdraw(tknAmt, _burnAmt); + emit LogWithdraw(tknAmt, _burnAmt); } function addInsurance(uint tknAmt) external payable { - baseToken.safeTransferFrom(msg.sender, address(this), tknAmt); - insuranceAmt += tknAmt; - emit LogAddInsurance(tknAmt); + baseToken.safeTransferFrom(msg.sender, address(this), tknAmt); + insuranceAmt += tknAmt; + emit LogAddInsurance(tknAmt); } function shutdown() external { - require(msg.sender == instaIndex.master(), "not-master"); - paused() ? _unpause() : _pause(); + require(msg.sender == instaIndex.master(), "not-master"); + paused() ? _unpause() : _pause(); } }