From 53838909ec4cb2e866c43ebc7d46ef5d6b1feddb Mon Sep 17 00:00:00 2001 From: Samyak Jain <34437877+KaymasJain@users.noreply.github.com> Date: Sun, 6 Sep 2020 22:08:29 +1000 Subject: [PATCH 01/12] new updates implemented --- contracts/pools/erc20.sol | 80 +++++++++++++++++++++----------------- contracts/pools/eth.sol | 82 ++++++++++++++++++++++----------------- contracts/registry.sol | 38 ++++++++++++++---- 3 files changed, 122 insertions(+), 78 deletions(-) diff --git a/contracts/pools/erc20.sol b/contracts/pools/erc20.sol index 171cf59..32a98b0 100644 --- a/contracts/pools/erc20.sol +++ b/contracts/pools/erc20.sol @@ -21,9 +21,10 @@ interface IndexInterface { interface RegistryInterface { function chief(address) external view returns (bool); function poolLogic(address) external returns (address); - function insureFee(address) external view returns (uint); + function fee(address) external view returns (uint); function withdrawalFee(address) external view returns (uint); function isDsa(address, address) external view returns (bool); + function checkSettleLogics(address, address[] calldata) external view returns (bool); } interface RateInterface { @@ -38,8 +39,8 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { 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 LogAddFee(uint amount); + event LogWithdrawFee(uint amount); event LogPausePool(bool); IERC20 public immutable baseToken; // Base token. Eg:- DAI, USDC, etc. @@ -48,7 +49,7 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { uint private tokenBalance; // total token balance uint public exchangeRate; // initial 1 token = 1 - uint public insuranceAmt; // insurance amount to keep pool safe + uint public feeAmt; // fee collected on profits constructor( address _registry, @@ -62,7 +63,7 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { } modifier isChief() { - require(registry.chief(msg.sender) || msg.sender == instaIndex.master(), "not-chief"); + require(registry.chief(msg.sender) || msg.sender == instaIndex.master() || msg.sender == address(this), "not-chief"); _; } @@ -99,43 +100,52 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { function setExchangeRate() public isChief { uint _previousRate = exchangeRate; uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); - _totalToken = sub(_totalToken, insuranceAmt); + _totalToken = sub(_totalToken, feeAmt); 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); - insuranceAmt = 0; - _currentRate = getCurrentRate(tokenBalance); - } } else { // profit => add to insurance amount - uint insureFeeAmt = wmul(sub(_totalToken, tokenBalance), registry.insureFee(address(this))); - insuranceAmt = add(insuranceAmt, insureFeeAmt); - tokenBalance = sub(_totalToken, insureFeeAmt); + uint _newFee = wmul(sub(_totalToken, tokenBalance), registry.fee(address(this))); + feeAmt = add(feeAmt, _newFee); + tokenBalance = sub(_totalToken, _newFee); _currentRate = getCurrentRate(tokenBalance); } exchangeRate = _currentRate; - emit LogExchangeRate(exchangeRate, tokenBalance, insuranceAmt); + emit LogExchangeRate(exchangeRate, tokenBalance, feeAmt); + } + + /** + * @dev Delegate the calls to Connector And this function is ran by cast(). + * @param _target Target to of Connector. + * @param _data CallData of function in Connector. + */ + function spell(address _target, bytes memory _data) internal { + require(_target != address(0), "target-invalid"); + assembly { + let succeeded := delegatecall(gas(), _target, add(_data, 0x20), mload(_data), 0, 0) + + switch iszero(succeeded) + case 1 { + // throw if delegatecall failed + let size := returndatasize() + returndatacopy(0x00, 0x00, size) + revert(0x00, size) + } + } } /** * @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 + * @param _data array of connector's function calldata */ - 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); + function settle(address[] calldata _targets, bytes[] calldata _data) external isChief { + require(_targets.length == _data.length , "array-length-invalid"); + require(registry.checkSettleLogics(address(this), _targets), "not-logic"); + for (uint i = 0; i < _targets.length; i++) { + spell(_targets[i], _data[i]); } - require(dsaWallet.isAuth(address(this)), "token-pool-not-auth"); setExchangeRate(); emit LogSettle(block.number); } @@ -185,7 +195,7 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { uint _feeAmt; if (_withdrawalFee > 0) { _feeAmt = wmul(_tknAmt, _withdrawalFee); - insuranceAmt = add(insuranceAmt, _feeAmt); + feeAmt = add(feeAmt, _feeAmt); _tknAmt = sub(_tknAmt, _feeAmt); } @@ -198,10 +208,10 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { * @dev Add Insurance to the pool. * @param tknAmt insurance token amount to add */ - function addInsurance(uint tknAmt) external { + function addFee(uint tknAmt) external { baseToken.safeTransferFrom(msg.sender, address(this), tknAmt); - insuranceAmt = add(insuranceAmt, tknAmt); - emit LogAddInsurance(tknAmt); + feeAmt = add(feeAmt, tknAmt); + emit LogAddFee(tknAmt); } /** @@ -209,12 +219,12 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { * @notice only master can call this function. * @param tknAmt insurance token amount to remove */ - function withdrawInsurance(uint tknAmt) external { + function withdrawFee(uint tknAmt) external { require(msg.sender == instaIndex.master(), "not-master"); - require(tknAmt <= insuranceAmt, "not-enough-insurance"); + require(tknAmt <= feeAmt, "not-enough-insurance"); baseToken.safeTransfer(msg.sender, tknAmt); - insuranceAmt = sub(insuranceAmt, tknAmt); - emit LogWithdrawInsurance(tknAmt); + feeAmt = sub(feeAmt, tknAmt); + emit LogWithdrawFee(tknAmt); } /** diff --git a/contracts/pools/eth.sol b/contracts/pools/eth.sol index 996e294..2553d8c 100644 --- a/contracts/pools/eth.sol +++ b/contracts/pools/eth.sol @@ -21,9 +21,10 @@ interface IndexInterface { interface RegistryInterface { function chief(address) external view returns (bool); function poolLogic(address) external returns (address); - function insureFee(address) external view returns (uint); + function fee(address) external view returns (uint); function withdrawalFee(address) external view returns (uint); function isDsa(address, address) external view returns (bool); + function checkSettleLogics(address, address[] calldata) external view returns (bool); } interface RateInterface { @@ -38,17 +39,17 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { 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 LogAddFee(uint amount); + event LogWithdrawFee(uint amount); event LogPausePool(bool); + IERC20 public immutable baseToken; // Base token. RegistryInterface public immutable registry; // Pool Registry IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); - IERC20 public immutable baseToken; // Base token. uint private tokenBalance; // total token balance uint public exchangeRate = 10 ** 18; // initial 1 token = 1 - uint public insuranceAmt; // insurance amount to keep pool safe + uint public feeAmt; // fee collected on profits constructor( address _registry, @@ -92,47 +93,56 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { /** * @dev sets exchange rates - */ + */ function setExchangeRate() public isChief { uint _previousRate = exchangeRate; uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); - _totalToken = sub(_totalToken, insuranceAmt); + _totalToken = sub(_totalToken, feeAmt); 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); - insuranceAmt = 0; - _currentRate = getCurrentRate(tokenBalance); - } } else { // profit => add to insurance amount - uint insureFeeAmt = wmul(sub(_totalToken, tokenBalance), registry.insureFee(address(this))); - insuranceAmt = add(insuranceAmt, insureFeeAmt); - tokenBalance = sub(_totalToken, insureFeeAmt); + uint _newFee = wmul(sub(_totalToken, tokenBalance), registry.fee(address(this))); + feeAmt = add(feeAmt, _newFee); + tokenBalance = sub(_totalToken, _newFee); _currentRate = getCurrentRate(tokenBalance); } exchangeRate = _currentRate; - emit LogExchangeRate(exchangeRate, tokenBalance, insuranceAmt); + emit LogExchangeRate(exchangeRate, tokenBalance, feeAmt); + } + + /** + * @dev Delegate the calls to Connector And this function is ran by cast(). + * @param _target Target to of Connector. + * @param _data CallData of function in Connector. + */ + function spell(address _target, bytes memory _data) internal { + require(_target != address(0), "target-invalid"); + assembly { + let succeeded := delegatecall(gas(), _target, add(_data, 0x20), mload(_data), 0, 0) + + switch iszero(succeeded) + case 1 { + // throw if delegatecall failed + let size := returndatasize() + returndatacopy(0x00, 0x00, size) + revert(0x00, size) + } + } } /** * @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 + * @param _data array of connector's function calldata */ - 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); + function settle(address[] calldata _targets, bytes[] calldata _data) external isChief { + require(_targets.length == _data.length , "array-length-invalid"); + require(registry.checkSettleLogics(address(this), _targets), "not-logic"); + for (uint i = 0; i < _targets.length; i++) { + spell(_targets[i], _data[i]); } - require(dsaWallet.isAuth(address(this)), "token-pool-not-auth"); setExchangeRate(); emit LogSettle(block.number); } @@ -181,7 +191,7 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { uint _feeAmt; if (_withdrawalFee > 0) { _feeAmt = wmul(_tknAmt, _withdrawalFee); - insuranceAmt = add(insuranceAmt, _feeAmt); + feeAmt = add(feeAmt, _feeAmt); _tknAmt = sub(_tknAmt, _feeAmt); } @@ -194,10 +204,10 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { * @dev Add Insurance to the pool. * @param tknAmt insurance token amount to add */ - function addInsurance(uint tknAmt) external payable { + function addFee(uint tknAmt) external payable { require(tknAmt == msg.value, "unmatched-amount"); - insuranceAmt = add(insuranceAmt, tknAmt); - emit LogAddInsurance(tknAmt); + feeAmt = add(feeAmt, tknAmt); + emit LogAddFee(tknAmt); } /** @@ -205,12 +215,12 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { * @notice only master can call this function. * @param tknAmt insurance token amount to remove */ - function withdrawInsurance(uint tknAmt) external { + function withdrawFee(uint tknAmt) external { require(msg.sender == instaIndex.master(), "not-master"); - require(tknAmt <= insuranceAmt, "not-enough-insurance"); + require(tknAmt <= feeAmt, "not-enough-insurance"); msg.sender.transfer(tknAmt); - insuranceAmt = sub(insuranceAmt, tknAmt); - emit LogWithdrawInsurance(tknAmt); + feeAmt = sub(feeAmt, tknAmt); + emit LogWithdrawFee(tknAmt); } /** diff --git a/contracts/registry.sol b/contracts/registry.sol index eead9fc..1b1484b 100644 --- a/contracts/registry.sol +++ b/contracts/registry.sol @@ -16,12 +16,14 @@ contract Registry { event LogRemoveSigner(address indexed signer); event LogUpdatePool(address pool, bool poolState); event LogUpdatePoolLogic(address pool, address newLogic); - event LogUpdateInsureFee(address pool, uint newFee); + event LogUpdateFee(address pool, uint newFee); event LogUpdateWithdrawalFee(address pool, uint newFee); event LogAddPool(address indexed token, address indexed pool); event LogRemovePool(address indexed token, address indexed pool); event LogNewDSA(address indexed pool, address indexed dsa); event LogRemoveDSA(address indexed pool, address indexed dsa); + event LogAddSettleLogic(address indexed pool, address indexed logic); + event LogRemoveSettleLogic(address indexed pool, address indexed logic); IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); @@ -31,8 +33,9 @@ contract Registry { mapping (address => address) public poolToken; mapping (address => address) public poolLogic; mapping (address => uint) public poolCap; - mapping (address => uint) public insureFee; + mapping (address => uint) public fee; mapping (address => uint) public withdrawalFee; + mapping (address => mapping(address => bool)) public settleLogic; mapping (address => mapping(address => bool)) public isDsa; // pool => dsa => bool mapping (address => address[]) public dsaArr; // pool => all dsa in array @@ -145,12 +148,12 @@ contract Registry { * @param _pool pool address * @param _newFee new fee amount */ - function updateInsureFee(address _pool, uint _newFee) external isMaster { + function updateFee(address _pool, uint _newFee) external isMaster { require(isPool[_pool], "not-pool"); - require(_newFee < 10 ** 18, "insure-fee-limit-reached"); - require(insureFee[_pool] != _newFee, "same-pool-fee"); - insureFee[_pool] = _newFee; - emit LogUpdateInsureFee(_pool, _newFee); + require(_newFee < 3 * 10 ** 17, "insure-fee-limit-reached"); + require(fee[_pool] != _newFee, "same-pool-fee"); + fee[_pool] = _newFee; + emit LogUpdateFee(_pool, _newFee); } /** @@ -166,6 +169,27 @@ contract Registry { emit LogUpdateWithdrawalFee(_pool, _newFee); } + function addSettleLogic(address _pool, address _logic) external isMaster { + require(isPool[_pool], "not-pool"); + settleLogic[_pool][_logic] = true; + emit LogAddSettleLogic(_pool, _logic); + } + + function removeSettleLogic(address _pool, address _logic) external isMaster { + require(isPool[_pool], "not-pool"); + delete settleLogic[_pool][_logic]; + emit LogRemoveSettleLogic(_pool, _logic); + } + + function checkSettleLogics(address _pool, address[] calldata _logics) external view returns(bool) { + for (uint i = 0; i < _logics.length; i++) { + if (!settleLogic[_pool][_logics[i]]) { + return false; + } + } + return true; + } + /** * @dev add dsa for a pool * @param _pool pool address From c2855db0f5e36f26aaebeb569d42ef24de0fe01f Mon Sep 17 00:00:00 2001 From: Sowmay Jain Date: Sun, 6 Sep 2020 23:38:13 +1000 Subject: [PATCH 02/12] edited comments --- contracts/pools/eth.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/pools/eth.sol b/contracts/pools/eth.sol index 2553d8c..697ff3f 100644 --- a/contracts/pools/eth.sol +++ b/contracts/pools/eth.sol @@ -75,7 +75,7 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { 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)) { // pool base ETH + if (token == address(0)) { // pool ETH payable(_dsa).transfer(amount); } else { // non-pool other tokens IERC20(token).safeTransfer(_dsa, amount); @@ -100,9 +100,9 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { _totalToken = sub(_totalToken, feeAmt); uint _currentRate = getCurrentRate(_totalToken); require(_currentRate != 0, "current-rate-is-zero"); - if (_currentRate > _previousRate) { // loss => deduct partially/fully from insurance amount + if (_currentRate > _previousRate) { _currentRate = _previousRate; - } else { // profit => add to insurance amount + } else { uint _newFee = wmul(sub(_totalToken, tokenBalance), registry.fee(address(this))); feeAmt = add(feeAmt, _newFee); tokenBalance = sub(_totalToken, _newFee); From cba07b85997a4f61b3ba6e50e777a5ebf1f7a5f0 Mon Sep 17 00:00:00 2001 From: Sowmay Jain Date: Mon, 7 Sep 2020 00:26:08 +1000 Subject: [PATCH 03/12] refactoring (WIP) --- contracts/pools/eth.sol | 96 ++++++++++++++++------------------------- contracts/registry.sol | 33 ++++---------- 2 files changed, 45 insertions(+), 84 deletions(-) diff --git a/contracts/pools/eth.sol b/contracts/pools/eth.sol index 697ff3f..fd808cf 100644 --- a/contracts/pools/eth.sol +++ b/contracts/pools/eth.sol @@ -22,7 +22,6 @@ interface RegistryInterface { function chief(address) external view returns (bool); function poolLogic(address) external returns (address); function fee(address) external view returns (uint); - function withdrawalFee(address) external view returns (uint); function isDsa(address, address) external view returns (bool); function checkSettleLogics(address, address[] calldata) external view returns (bool); } @@ -38,8 +37,7 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { event LogExchangeRate(uint exchangeRate, uint tokenBalance, uint insuranceAmt); 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 LogAddFee(uint amount); + event LogWithdraw(address indexed user, uint withdrawAmt, uint poolBurnAmt); event LogWithdrawFee(uint amount); event LogPausePool(bool); @@ -96,16 +94,16 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { */ function setExchangeRate() public isChief { uint _previousRate = exchangeRate; - uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); - _totalToken = sub(_totalToken, feeAmt); - uint _currentRate = getCurrentRate(_totalToken); + uint totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); + totalToken = sub(totalToken, feeAmt); + uint _currentRate = getCurrentRate(totalToken); require(_currentRate != 0, "current-rate-is-zero"); if (_currentRate > _previousRate) { _currentRate = _previousRate; } else { - uint _newFee = wmul(sub(_totalToken, tokenBalance), registry.fee(address(this))); - feeAmt = add(feeAmt, _newFee); - tokenBalance = sub(_totalToken, _newFee); + uint newFee = wmul(sub(totalToken, tokenBalance), registry.fee(address(this))); + feeAmt = add(feeAmt, newFee); + tokenBalance = sub(totalToken, newFee); _currentRate = getCurrentRate(tokenBalance); } exchangeRate = _currentRate; @@ -150,77 +148,55 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { /** * @dev Deposit token. * @param tknAmt token amount - * @return _mintAmt amount of wrap token minted + * @return mintAmt amount of wrap token minted */ - function deposit(uint tknAmt) public whenNotPaused payable returns (uint _mintAmt) { + function deposit(uint tknAmt) public whenNotPaused payable returns (uint mintAmt) { require(tknAmt == msg.value, "unmatched-amount"); tokenBalance = add(tokenBalance, tknAmt); - _mintAmt = wmul(msg.value, exchangeRate); - _mint(msg.sender, _mintAmt); + mintAmt = wmul(msg.value, exchangeRate); + _mint(msg.sender, mintAmt); - emit LogDeposit(msg.sender, 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 + * @param target withdraw tokens to address + * @return "wdAmt" amount of token withdrawn */ - function withdraw(uint tknAmt, address to) external nonReentrant whenNotPaused returns (uint _tknAmt) { - uint poolBal = address(this).balance; - require(to != address(0), "to-address-not-vaild"); - uint _bal = balanceOf(msg.sender); - uint _tknBal = wdiv(_bal, exchangeRate); - uint _burnAmt; - if (tknAmt >= _tknBal) { - _burnAmt = _bal; - _tknAmt = _tknBal; + function withdraw(uint tknAmt, address target) external nonReentrant whenNotPaused returns (uint wdAmt) { + require(target != address(0), "invalid-target-address"); + uint userBal = wdiv(balanceOf(msg.sender), exchangeRate); + uint burnAmt; + if (tknAmt >= userBal) { + burnAmt = balanceOf(msg.sender); + wdAmt = userBal; } else { - _burnAmt = wmul(tknAmt, exchangeRate); - _tknAmt = tknAmt; + burnAmt = wmul(tknAmt, exchangeRate); + wdAmt = tknAmt; } - require(_tknAmt <= poolBal, "not-enough-liquidity-available"); + require(wdAmt <= address(this).balance, "not-enough-liquidity-available"); - tokenBalance = sub(tokenBalance, _tknAmt); + _burn(msg.sender, burnAmt); + tokenBalance = sub(tokenBalance, wdAmt); + payable(target).transfer(wdAmt); - _burn(msg.sender, _burnAmt); - - uint _withdrawalFee = registry.withdrawalFee(address(this)); - uint _feeAmt; - if (_withdrawalFee > 0) { - _feeAmt = wmul(_tknAmt, _withdrawalFee); - feeAmt = add(feeAmt, _feeAmt); - _tknAmt = sub(_tknAmt, _feeAmt); - } - - payable(to).transfer(_tknAmt); - - emit LogWithdraw(msg.sender, _tknAmt, _burnAmt, _feeAmt); + emit LogWithdraw(msg.sender, wdAmt, burnAmt); } /** - * @dev Add Insurance to the pool. - * @param tknAmt insurance token amount to add + * @dev withdraw fee from the pool + * @notice only master can call this function + * @param wdAmt fee amount to withdraw */ - function addFee(uint tknAmt) external payable { - require(tknAmt == msg.value, "unmatched-amount"); - feeAmt = add(feeAmt, tknAmt); - emit LogAddFee(tknAmt); - } - - /** - * @dev Withdraw Insurance from the pool. - * @notice only master can call this function. - * @param tknAmt insurance token amount to remove - */ - function withdrawFee(uint tknAmt) external { + function withdrawFee(uint wdAmt) external { require(msg.sender == instaIndex.master(), "not-master"); - require(tknAmt <= feeAmt, "not-enough-insurance"); - msg.sender.transfer(tknAmt); - feeAmt = sub(feeAmt, tknAmt); - emit LogWithdrawFee(tknAmt); + if (wdAmt > feeAmt) wdAmt = feeAmt; + msg.sender.transfer(wdAmt); + feeAmt = sub(feeAmt, wdAmt); + emit LogWithdrawFee(wdAmt); } /** diff --git a/contracts/registry.sol b/contracts/registry.sol index 1b1484b..24b3b95 100644 --- a/contracts/registry.sol +++ b/contracts/registry.sol @@ -16,8 +16,7 @@ contract Registry { event LogRemoveSigner(address indexed signer); event LogUpdatePool(address pool, bool poolState); event LogUpdatePoolLogic(address pool, address newLogic); - event LogUpdateFee(address pool, uint newFee); - event LogUpdateWithdrawalFee(address pool, uint newFee); + event LogUpdateTariff(address pool, uint newTariff); event LogAddPool(address indexed token, address indexed pool); event LogRemovePool(address indexed token, address indexed pool); event LogNewDSA(address indexed pool, address indexed dsa); @@ -33,8 +32,7 @@ contract Registry { mapping (address => address) public poolToken; mapping (address => address) public poolLogic; mapping (address => uint) public poolCap; - mapping (address => uint) public fee; - mapping (address => uint) public withdrawalFee; + mapping (address => uint) public tariff; mapping (address => mapping(address => bool)) public settleLogic; mapping (address => mapping(address => bool)) public isDsa; // pool => dsa => bool mapping (address => address[]) public dsaArr; // pool => all dsa in array @@ -144,29 +142,16 @@ contract Registry { } /** - * @dev update pool insure fee + * @dev update pool tariff * @param _pool pool address - * @param _newFee new fee amount + * @param _newTariff new tariff amount */ - function updateFee(address _pool, uint _newFee) external isMaster { + function updateTariff(address _pool, uint _newTariff) external isMaster { require(isPool[_pool], "not-pool"); - require(_newFee < 3 * 10 ** 17, "insure-fee-limit-reached"); - require(fee[_pool] != _newFee, "same-pool-fee"); - fee[_pool] = _newFee; - emit LogUpdateFee(_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"); - require(withdrawalFee[_pool] != _newFee, "same-pool-fee"); - withdrawalFee[_pool] = _newFee; - emit LogUpdateWithdrawalFee(_pool, _newFee); + require(_newTariff < 3 * 10 ** 17, "insure-tariff-limit-reached"); + require(tariff[_pool] != _newTariff, "same-pool-tariff"); + tariff[_pool] = _newTariff; + emit LogUpdateTariff(_pool, _newTariff); } function addSettleLogic(address _pool, address _logic) external isMaster { From 1576a2bfc8904b3538d97e412dd167aca570ba8b Mon Sep 17 00:00:00 2001 From: Sowmay Jain Date: Mon, 7 Sep 2020 01:19:39 +1000 Subject: [PATCH 04/12] mike drop --- contracts/pools/eth.sol | 79 +++++++++------------------- contracts/registry.sol | 114 +++++++++++++--------------------------- 2 files changed, 62 insertions(+), 131 deletions(-) diff --git a/contracts/pools/eth.sol b/contracts/pools/eth.sol index fd808cf..628cd9d 100644 --- a/contracts/pools/eth.sol +++ b/contracts/pools/eth.sol @@ -8,11 +8,6 @@ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import { DSMath } from "../libs/safeMath.sol"; -interface AccountInterface { - function isAuth(address) external view returns(bool); - function cast(address[] calldata _targets, bytes[] calldata _datas, address _origin) external payable; -} - interface IndexInterface { function master() external view returns (address); function build(address _owner, uint accountVersion, address _origin) external returns (address _account); @@ -22,7 +17,6 @@ interface RegistryInterface { function chief(address) external view returns (bool); function poolLogic(address) external returns (address); function fee(address) external view returns (uint); - function isDsa(address, address) external view returns (bool); function checkSettleLogics(address, address[] calldata) external view returns (bool); } @@ -33,7 +27,6 @@ interface RateInterface { contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { using SafeERC20 for IERC20; - event LogDeploy(address indexed dsa, address indexed token, uint amount); event LogExchangeRate(uint exchangeRate, uint tokenBalance, uint insuranceAmt); event LogSettle(uint settleBlock); event LogDeposit(address indexed user, uint depositAmt, uint poolMintAmt); @@ -45,7 +38,6 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { RegistryInterface public immutable registry; // Pool Registry IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); - uint private tokenBalance; // total token balance uint public exchangeRate = 10 ** 18; // initial 1 token = 1 uint public feeAmt; // fee collected on profits @@ -64,28 +56,11 @@ contract PoolETH 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)) { // pool ETH - payable(_dsa).transfer(amount); - } else { // non-pool other tokens - IERC20(token).safeTransfer(_dsa, amount); - } - emit LogDeploy(_dsa, token, amount); - } - /** * @dev get pool token rate * @param tokenAmt total token amount */ - function getCurrentRate(uint tokenAmt) public view returns (uint) { + function getCurrentRate(uint tokenAmt) internal returns (uint) { return wdiv(totalSupply(), tokenAmt); } @@ -93,25 +68,26 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { * @dev sets exchange rates */ function setExchangeRate() public isChief { - uint _previousRate = exchangeRate; - uint totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); - totalToken = sub(totalToken, feeAmt); - uint _currentRate = getCurrentRate(totalToken); - require(_currentRate != 0, "current-rate-is-zero"); - if (_currentRate > _previousRate) { - _currentRate = _previousRate; + uint _prevRate = exchangeRate; + uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); + _totalToken = sub(_totalToken, feeAmt); + uint _newRate = getCurrentRate(_totalToken); + require(_newRate != 0, "current-rate-is-zero"); + if (_newRate > _prevRate) { + _newRate = _prevRate; } else { - uint newFee = wmul(sub(totalToken, tokenBalance), registry.fee(address(this))); - feeAmt = add(feeAmt, newFee); - tokenBalance = sub(totalToken, newFee); - _currentRate = getCurrentRate(tokenBalance); + uint _tokenBal = wdiv(totalSupply(), _prevRate); + uint _newFee = wmul(sub(_totalToken, _tokenBal), registry.fee(address(this))); + feeAmt = add(feeAmt, _newFee); + _tokenBal = sub(_totalToken, _newFee); + _newRate = getCurrentRate(_tokenBal); } - exchangeRate = _currentRate; - emit LogExchangeRate(exchangeRate, tokenBalance, feeAmt); + exchangeRate = _newRate; + emit LogExchangeRate(exchangeRate, _tokenBal, feeAmt); } /** - * @dev Delegate the calls to Connector And this function is ran by cast(). + * @dev delegate the calls to connector and this function is ran by settle() * @param _target Target to of Connector. * @param _data CallData of function in Connector. */ @@ -141,7 +117,6 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { for (uint i = 0; i < _targets.length; i++) { spell(_targets[i], _data[i]); } - setExchangeRate(); emit LogSettle(block.number); } @@ -152,11 +127,8 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { */ function deposit(uint tknAmt) public whenNotPaused payable returns (uint mintAmt) { require(tknAmt == msg.value, "unmatched-amount"); - tokenBalance = add(tokenBalance, tknAmt); - mintAmt = wmul(msg.value, exchangeRate); _mint(msg.sender, mintAmt); - emit LogDeposit(msg.sender, tknAmt, mintAmt); } @@ -168,22 +140,21 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { */ function withdraw(uint tknAmt, address target) external nonReentrant whenNotPaused returns (uint wdAmt) { require(target != address(0), "invalid-target-address"); - uint userBal = wdiv(balanceOf(msg.sender), exchangeRate); - uint burnAmt; - if (tknAmt >= userBal) { - burnAmt = balanceOf(msg.sender); - wdAmt = userBal; + uint _userBal = wdiv(balanceOf(msg.sender), exchangeRate); + uint _burnAmt; + if (tknAmt >= _userBal) { + _burnAmt = balanceOf(msg.sender); + wdAmt = _userBal; } else { - burnAmt = wmul(tknAmt, exchangeRate); + _burnAmt = wmul(tknAmt, exchangeRate); wdAmt = tknAmt; } require(wdAmt <= address(this).balance, "not-enough-liquidity-available"); - _burn(msg.sender, burnAmt); - tokenBalance = sub(tokenBalance, wdAmt); + _burn(msg.sender, _burnAmt); payable(target).transfer(wdAmt); - emit LogWithdraw(msg.sender, wdAmt, burnAmt); + emit LogWithdraw(msg.sender, wdAmt, _burnAmt); } /** @@ -209,4 +180,4 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { } receive() external payable {} -} +} \ No newline at end of file diff --git a/contracts/registry.sol b/contracts/registry.sol index 24b3b95..5f0d818 100644 --- a/contracts/registry.sol +++ b/contracts/registry.sol @@ -14,28 +14,22 @@ contract Registry { event LogRemoveChief(address indexed chief); event LogAddSigner(address indexed signer); event LogRemoveSigner(address indexed signer); - event LogUpdatePool(address pool, bool poolState); - event LogUpdatePoolLogic(address pool, address newLogic); - event LogUpdateTariff(address pool, uint newTariff); + event LogUpdatePoolLogic(address token, address newLogic); + event LogUpdateFee(address token, uint newFee); event LogAddPool(address indexed token, address indexed pool); event LogRemovePool(address indexed token, address indexed pool); - event LogNewDSA(address indexed pool, address indexed dsa); - event LogRemoveDSA(address indexed pool, address indexed dsa); - event LogAddSettleLogic(address indexed pool, address indexed logic); - event LogRemoveSettleLogic(address indexed pool, address indexed logic); + event LogAddSettleLogic(address indexed token, address indexed logic); + event LogRemoveSettleLogic(address indexed token, address indexed logic); IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); mapping (address => bool) public chief; mapping (address => bool) public signer; - mapping (address => bool) public isPool; mapping (address => address) public poolToken; mapping (address => address) public poolLogic; mapping (address => uint) public poolCap; - mapping (address => uint) public tariff; + mapping (address => uint) public fee; mapping (address => mapping(address => bool)) public settleLogic; - mapping (address => mapping(address => bool)) public isDsa; // pool => dsa => bool - mapping (address => address[]) public dsaArr; // pool => all dsa in array modifier isMaster() { require(msg.sender == instaIndex.master(), "not-master"); @@ -47,10 +41,6 @@ contract Registry { _; } - function getDsaLength(address _pool) external view returns(uint) { - return dsaArr[_pool].length; - } - /** * @dev Enable New Chief. * @param _chief Address of the new chief. @@ -97,44 +87,36 @@ contract Registry { /** * @dev Add New Pool - * @param token ERC20 token address + * @param _token ERC20 token address * @param pool pool address */ - function addPool(address token, address pool) external isMaster { - require(token != address(0) && pool != address(0), "invalid-address"); - require(poolToken[token] == address(0), "pool-already-added"); - poolToken[token] = pool; - emit LogAddPool(token, pool); + function addPool(address _token, address pool) external isMaster { + require(_token != address(0) && pool != address(0), "invalid-token-address"); + require(poolToken[_token] == address(0), "pool-already-added"); + poolToken[_token] = pool; + emit LogAddPool(_token, pool); } /** * @dev Remove Pool - * @param token ERC20 token address + * @param _token ERC20 token address */ - function removePool(address token) external isMaster { - require(token != address(0), "invalid-address"); - require(poolToken[token] != address(0), "pool-already-removed"); - address poolAddr = poolToken[token]; - delete poolToken[token]; - emit LogRemovePool(token, poolAddr); - } - - /** - * @dev enable / disable pool - * @param _pool pool address - */ - function updatePool(address _pool) external isMaster { - isPool[_pool] = !isPool[_pool]; - emit LogUpdatePool(_pool, isPool[_pool]); + function removePool(address _token) external isMaster { + require(_token != address(0), "invalid-token-address"); + require(poolToken[_token] != address(0), "pool-already-removed"); + address poolAddr = poolToken[_token]; + delete poolToken[_token]; + emit LogRemovePool(_token, poolAddr); } /** * @dev update pool rate logic - * @param _pool pool address + * @param _token pool address * @param _newLogic new rate logic address */ - function updatePoolLogic(address _pool, address _newLogic) external isMaster { - require(isPool[_pool], "not-pool"); + function updatePoolLogic(address _token, address _newLogic) external isMaster { + address _pool = poolToken[_token]; + require(_pool != address(0), "invalid-pool"); require(_newLogic != address(0), "invalid-address"); require( poolLogic[_pool] != _newLogic, "same-pool-logic"); poolLogic[_pool] = _newLogic; @@ -142,26 +124,29 @@ contract Registry { } /** - * @dev update pool tariff + * @dev update pool fee * @param _pool pool address - * @param _newTariff new tariff amount + * @param _newFee new fee amount */ - function updateTariff(address _pool, uint _newTariff) external isMaster { - require(isPool[_pool], "not-pool"); - require(_newTariff < 3 * 10 ** 17, "insure-tariff-limit-reached"); - require(tariff[_pool] != _newTariff, "same-pool-tariff"); - tariff[_pool] = _newTariff; - emit LogUpdateTariff(_pool, _newTariff); + function updateFee(address _token, uint _newFee) external isMaster { + address _pool = poolToken[_token]; + require(_pool != address(0), "invalid-pool"); + require(_newFee < 3 * 10 ** 17, "insure-fee-limit-reached"); + require(fee[_pool] != _newFee, "same-pool-fee"); + fee[_pool] = _newFee; + emit LogUpdateFee(_pool, _newFee); } - function addSettleLogic(address _pool, address _logic) external isMaster { - require(isPool[_pool], "not-pool"); + function addSettleLogic(address _token, address _logic) external isMaster { + address _pool = poolToken[_token]; + require(_pool != address(0), "invalid-pool"); settleLogic[_pool][_logic] = true; emit LogAddSettleLogic(_pool, _logic); } - function removeSettleLogic(address _pool, address _logic) external isMaster { - require(isPool[_pool], "not-pool"); + function removeSettleLogic(address _token, address _logic) external isMaster { + address _pool = poolToken[_token]; + require(_pool != address(0), "invalid-pool"); delete settleLogic[_pool][_logic]; emit LogRemoveSettleLogic(_pool, _logic); } @@ -175,31 +160,6 @@ contract Registry { return true; } - /** - * @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)); - isDsa[_pool][_dsa] = true; - dsaArr[_pool].push(_dsa); - 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"); - delete isDsa[_pool][_dsa]; - emit LogRemoveDSA(_pool, _dsa); - } - constructor(address _chief) public { chief[_chief] = true; emit LogAddChief(_chief); From d40b4898e45ddafdb568230e542f6fab17882ee7 Mon Sep 17 00:00:00 2001 From: Samyak Jain <34437877+KaymasJain@users.noreply.github.com> Date: Mon, 7 Sep 2020 02:01:27 +1000 Subject: [PATCH 05/12] pool Cap and erc20 code update --- contracts/pools/erc20.sol | 335 ++++++++++++++++---------------------- contracts/pools/eth.sol | 14 +- contracts/registry.sol | 17 +- 3 files changed, 169 insertions(+), 197 deletions(-) diff --git a/contracts/pools/erc20.sol b/contracts/pools/erc20.sol index 32a98b0..89a4520 100644 --- a/contracts/pools/erc20.sol +++ b/contracts/pools/erc20.sol @@ -8,11 +8,6 @@ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import { DSMath } from "../libs/safeMath.sol"; -interface AccountInterface { - function isAuth(address) external view returns(bool); - function cast(address[] calldata _targets, bytes[] calldata _datas, address _origin) external payable; -} - interface IndexInterface { function master() external view returns (address); function build(address _owner, uint accountVersion, address _origin) external returns (address _account); @@ -22,8 +17,7 @@ interface RegistryInterface { function chief(address) external view returns (bool); function poolLogic(address) external returns (address); function fee(address) external view returns (uint); - function withdrawalFee(address) external view returns (uint); - function isDsa(address, address) external view returns (bool); + function poolCap(address) external view returns (uint); function checkSettleLogics(address, address[] calldata) external view returns (bool); } @@ -32,209 +26,168 @@ interface RateInterface { } contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { - using SafeERC20 for IERC20; + using SafeERC20 for IERC20; - event LogDeploy(address indexed dsa, address token, uint amount); - event LogExchangeRate(uint exchangeRate, uint tokenBalance, uint insuranceAmt); - 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 LogAddFee(uint amount); - event LogWithdrawFee(uint amount); - event LogPausePool(bool); + event LogDeploy(address indexed dsa, address token, uint amount); + event LogExchangeRate(uint exchangeRate, uint tokenBalance, uint insuranceAmt); + event LogSettle(uint settleBlock); + event LogDeposit(address indexed user, uint depositAmt, uint poolMintAmt); + event LogWithdraw(address indexed user, uint withdrawAmt, uint poolBurnAmt); + event LogAddFee(uint amount); + event LogWithdrawFee(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 + 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 - uint public exchangeRate; // initial 1 token = 1 - uint public feeAmt; // fee collected on profits + uint public exchangeRate; // initial 1 token = 1 + uint public feeAmt; // fee collected on profits - constructor( - address _registry, - string memory _name, - string memory _symbol, - address _baseToken - ) public ERC20(_name, _symbol) { - baseToken = IERC20(_baseToken); - registry = RegistryInterface(_registry); - exchangeRate = 10 ** uint(36 - ERC20(_baseToken).decimals()); - } + constructor( + address _registry, + string memory _name, + string memory _symbol, + address _baseToken + ) public ERC20(_name, _symbol) { + baseToken = IERC20(_baseToken); + registry = RegistryInterface(_registry); + exchangeRate = 10 ** uint(36 - ERC20(_baseToken).decimals()); + } - modifier isChief() { - require(registry.chief(msg.sender) || msg.sender == instaIndex.master() || msg.sender == address(this), "not-chief"); - _; - } + modifier isChief() { + require(registry.chief(msg.sender) || msg.sender == instaIndex.master(), "not-chief"); + _; + } - /** - * @dev Deploy assets to DSA. - * @param _dsa DSA address - * @param token token address - * @param amount token amount + /** + * @dev get pool token rate + * @param tokenAmt total 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)) { // pool base token - baseToken.safeTransfer(_dsa, amount); - } else if (token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE){ // non-pool ethereum - payable(_dsa).transfer(amount); - } else { // non-pool other tokens - IERC20(token).safeTransfer(_dsa, amount); - } - emit LogDeploy(_dsa, token, amount); - } + function getCurrentRate(uint tokenAmt) internal view returns (uint) { + return wdiv(totalSupply(), tokenAmt); + } - /** - * @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, feeAmt); - uint _currentRate = getCurrentRate(_totalToken); - require(_currentRate != 0, "current-rate-is-zero"); - if (_currentRate > _previousRate) { // loss => deduct partially/fully from insurance amount - _currentRate = _previousRate; - } else { // profit => add to insurance amount - uint _newFee = wmul(sub(_totalToken, tokenBalance), registry.fee(address(this))); - feeAmt = add(feeAmt, _newFee); - tokenBalance = sub(_totalToken, _newFee); - _currentRate = getCurrentRate(tokenBalance); - } - exchangeRate = _currentRate; - emit LogExchangeRate(exchangeRate, tokenBalance, feeAmt); - } - - /** - * @dev Delegate the calls to Connector And this function is ran by cast(). - * @param _target Target to of Connector. - * @param _data CallData of function in Connector. + /** + * @dev sets exchange rates */ - function spell(address _target, bytes memory _data) internal { - require(_target != address(0), "target-invalid"); - assembly { - let succeeded := delegatecall(gas(), _target, add(_data, 0x20), mload(_data), 0, 0) - - switch iszero(succeeded) - case 1 { - // throw if delegatecall failed - let size := returndatasize() - returndatacopy(0x00, 0x00, size) - revert(0x00, size) - } - } + function setExchangeRate() public { + require(msg.sender == address(this), "not-pool-address"); + uint _previousRate = exchangeRate; + uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); + _totalToken = sub(_totalToken, feeAmt); + uint _currentRate = getCurrentRate(_totalToken); + uint _tokenBal; + require(_currentRate != 0, "current-rate-is-zero"); + if (_currentRate > _previousRate) { // loss => deduct partially/fully from insurance amount + _currentRate = _previousRate; + } else { // profit => add to insurance amount + uint _newFee = wmul(sub(_totalToken, _tokenBal), registry.fee(address(this))); + feeAmt = add(feeAmt, _newFee); + _tokenBal = sub(_totalToken, _newFee); + _currentRate = getCurrentRate(_tokenBal); } + exchangeRate = _currentRate; + emit LogExchangeRate(exchangeRate, _tokenBal, feeAmt); + } - /** - * @dev Settle the assets on dsa and update exchange rate - * @param _targets array of connector's address - * @param _data array of connector's function calldata - */ - function settle(address[] calldata _targets, bytes[] calldata _data) external isChief { - require(_targets.length == _data.length , "array-length-invalid"); - require(registry.checkSettleLogics(address(this), _targets), "not-logic"); - for (uint i = 0; i < _targets.length; i++) { - spell(_targets[i], _data[i]); - } - setExchangeRate(); - emit LogSettle(block.number); + /** + * @dev Delegate the calls to Connector And this function is ran by cast(). + * @param _target Target to of Connector. + * @param _data CallData of function in Connector. + */ + function spell(address _target, bytes memory _data) internal { + require(_target != address(0), "target-invalid"); + assembly { + let succeeded := delegatecall(gas(), _target, add(_data, 0x20), mload(_data), 0, 0) + + switch iszero(succeeded) + case 1 { + // throw if delegatecall failed + let size := returndatasize() + returndatacopy(0x00, 0x00, size) + revert(0x00, size) + } } + } - /** - * @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); - _mintAmt = wmul(tknAmt, exchangeRate); - _mint(msg.sender, _mintAmt); - - emit LogDeposit(msg.sender, tknAmt, _mintAmt); + /** + * @dev Settle the assets on dsa and update exchange rate + * @param _targets array of connector's address + * @param _data array of connector's function calldata + */ + function settle(address[] calldata _targets, bytes[] calldata _data) external isChief { + require(_targets.length == _data.length , "array-length-invalid"); + require(registry.checkSettleLogics(address(this), _targets), "not-logic"); + for (uint i = 0; i < _targets.length; i++) { + spell(_targets[i], _data[i]); } + emit LogSettle(block.number); + } - /** - * @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(to != address(0), "to-address-not-vaild"); - uint _bal = balanceOf(msg.sender); - uint _tknBal = wdiv(_bal, exchangeRate); - uint _burnAmt; - if (tknAmt >= _tknBal) { - _burnAmt = _bal; - _tknAmt = _tknBal; - } else { - _burnAmt = wmul(tknAmt, exchangeRate); - _tknAmt = tknAmt; - } - require(_tknAmt <= poolBal, "not-enough-liquidity-available"); + /** + * @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"); + uint _tokenBal = wdiv(totalSupply(), exchangeRate); + uint _newTknBal = add(_tokenBal, tknAmt); + require(_newTknBal < registry.poolCap(address(this)), "unmatched-amount"); + baseToken.safeTransferFrom(msg.sender, address(this), tknAmt); + _mintAmt = wmul(tknAmt, exchangeRate); + _mint(msg.sender, _mintAmt); + emit LogDeposit(msg.sender, tknAmt, _mintAmt); + } - tokenBalance = sub(tokenBalance, _tknAmt); - - _burn(msg.sender, _burnAmt); - - uint _withdrawalFee = registry.withdrawalFee(address(this)); - uint _feeAmt; - if (_withdrawalFee > 0) { - _feeAmt = wmul(_tknAmt, _withdrawalFee); - feeAmt = add(feeAmt, _feeAmt); - _tknAmt = sub(_tknAmt, _feeAmt); - } - - baseToken.safeTransfer(to, _tknAmt); - - emit LogWithdraw(msg.sender, _tknAmt, _burnAmt, _feeAmt); + /** + * @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) { + require(to != address(0), "to-address-not-vaild"); + uint _userBal = wdiv(balanceOf(msg.sender), exchangeRate); + uint _burnAmt; + if (tknAmt >= _userBal) { + _burnAmt = balanceOf(msg.sender); + _tknAmt = _userBal; + } else { + _burnAmt = wmul(tknAmt, exchangeRate); + _tknAmt = tknAmt; } + require(_tknAmt <= baseToken.balanceOf(address(this)), "not-enough-liquidity-available"); - /** - * @dev Add Insurance to the pool. - * @param tknAmt insurance token amount to add - */ - function addFee(uint tknAmt) external { - baseToken.safeTransferFrom(msg.sender, address(this), tknAmt); - feeAmt = add(feeAmt, tknAmt); - emit LogAddFee(tknAmt); - } + _burn(msg.sender, _burnAmt); + baseToken.safeTransfer(to, _tknAmt); - /** - * @dev Withdraw Insurance from the pool. - * @notice only master can call this function. - * @param tknAmt insurance token amount to remove - */ - function withdrawFee(uint tknAmt) external { - require(msg.sender == instaIndex.master(), "not-master"); - require(tknAmt <= feeAmt, "not-enough-insurance"); - baseToken.safeTransfer(msg.sender, tknAmt); - feeAmt = sub(feeAmt, tknAmt); - emit LogWithdrawFee(tknAmt); - } + emit LogWithdraw(msg.sender, _tknAmt, _burnAmt); + } - /** - * @dev Shut the pool. - * @notice only master can call this function. - */ - function shutdown() external { - require(msg.sender == instaIndex.master(), "not-master"); - paused() ? _unpause() : _pause(); - } + /** + * @dev Withdraw Insurance from the pool. + * @notice only master can call this function. + * @param wdAmt insurance token amount to remove + */ + function withdrawFee(uint wdAmt) external { + require(msg.sender == instaIndex.master(), "not-master"); + if (wdAmt > feeAmt) wdAmt = feeAmt; + baseToken.safeTransfer(msg.sender, wdAmt); + feeAmt = sub(feeAmt, wdAmt); + emit LogWithdrawFee(wdAmt); + } + + /** + * @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 {} - receive() external payable {} } diff --git a/contracts/pools/eth.sol b/contracts/pools/eth.sol index 628cd9d..8dedd21 100644 --- a/contracts/pools/eth.sol +++ b/contracts/pools/eth.sol @@ -17,6 +17,7 @@ interface RegistryInterface { function chief(address) external view returns (bool); function poolLogic(address) external returns (address); function fee(address) external view returns (uint); + function poolCap(address) external view returns (uint); function checkSettleLogics(address, address[] calldata) external view returns (bool); } @@ -60,23 +61,25 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { * @dev get pool token rate * @param tokenAmt total token amount */ - function getCurrentRate(uint tokenAmt) internal returns (uint) { + function getCurrentRate(uint tokenAmt) internal view returns (uint) { return wdiv(totalSupply(), tokenAmt); } /** * @dev sets exchange rates */ - function setExchangeRate() public isChief { + function setExchangeRate() public { + require(msg.sender == address(this), "not-pool-address"); uint _prevRate = exchangeRate; uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); _totalToken = sub(_totalToken, feeAmt); uint _newRate = getCurrentRate(_totalToken); + uint _tokenBal; require(_newRate != 0, "current-rate-is-zero"); if (_newRate > _prevRate) { _newRate = _prevRate; } else { - uint _tokenBal = wdiv(totalSupply(), _prevRate); + _tokenBal = wdiv(totalSupply(), _prevRate); uint _newFee = wmul(sub(_totalToken, _tokenBal), registry.fee(address(this))); feeAmt = add(feeAmt, _newFee); _tokenBal = sub(_totalToken, _newFee); @@ -127,6 +130,9 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { */ function deposit(uint tknAmt) public whenNotPaused payable returns (uint mintAmt) { require(tknAmt == msg.value, "unmatched-amount"); + uint _tokenBal = wdiv(totalSupply(), exchangeRate); + uint _newTknBal = add(_tokenBal, tknAmt); + require(_newTknBal < registry.poolCap(address(this)), "unmatched-amount"); mintAmt = wmul(msg.value, exchangeRate); _mint(msg.sender, mintAmt); emit LogDeposit(msg.sender, tknAmt, mintAmt); @@ -136,7 +142,7 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { * @dev Withdraw tokens. * @param tknAmt token amount * @param target withdraw tokens to address - * @return "wdAmt" amount of token withdrawn + * @return wdAmt amount of token withdrawn */ function withdraw(uint tknAmt, address target) external nonReentrant whenNotPaused returns (uint wdAmt) { require(target != address(0), "invalid-target-address"); diff --git a/contracts/registry.sol b/contracts/registry.sol index 5f0d818..50d79fc 100644 --- a/contracts/registry.sol +++ b/contracts/registry.sol @@ -16,6 +16,7 @@ contract Registry { event LogRemoveSigner(address indexed signer); event LogUpdatePoolLogic(address token, address newLogic); event LogUpdateFee(address token, uint newFee); + event LogUpdateCap(address token, uint newFee); event LogAddPool(address indexed token, address indexed pool); event LogRemovePool(address indexed token, address indexed pool); event LogAddSettleLogic(address indexed token, address indexed logic); @@ -118,14 +119,14 @@ contract Registry { address _pool = poolToken[_token]; require(_pool != address(0), "invalid-pool"); require(_newLogic != address(0), "invalid-address"); - require( poolLogic[_pool] != _newLogic, "same-pool-logic"); + require(poolLogic[_pool] != _newLogic, "same-pool-logic"); poolLogic[_pool] = _newLogic; emit LogUpdatePoolLogic(_pool, _newLogic); } /** * @dev update pool fee - * @param _pool pool address + * @param _token pool address * @param _newFee new fee amount */ function updateFee(address _token, uint _newFee) external isMaster { @@ -137,6 +138,18 @@ contract Registry { emit LogUpdateFee(_pool, _newFee); } + /** + * @dev update pool fee + * @param _token pool address + * @param _newCap new fee amount + */ + function updateCap(address _token, uint _newCap) external isMaster { + address _pool = poolToken[_token]; + require(_pool != address(0), "invalid-pool"); + poolCap[_pool] = _newCap; + emit LogUpdateCap(_pool, _newCap); + } + function addSettleLogic(address _token, address _logic) external isMaster { address _pool = poolToken[_token]; require(_pool != address(0), "invalid-pool"); From d0da53a4453488a93f04b2a849dfd17ac0f66d18 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Mon, 7 Sep 2020 02:41:23 +0530 Subject: [PATCH 06/12] Flusher changes and added flusherLogic --- contracts/deployer.sol | 67 ++++++++++--------- contracts/flusher.sol | 146 +++++++---------------------------------- contracts/registry.sol | 16 +++++ 3 files changed, 71 insertions(+), 158 deletions(-) diff --git a/contracts/deployer.sol b/contracts/deployer.sol index cad6c82..5b32762 100644 --- a/contracts/deployer.sol +++ b/contracts/deployer.sol @@ -1,46 +1,44 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.6.8; -interface IProxy { - function setBasic(address, address) external; -} - contract Deployer { - event LogNewProxy(address indexed owner, address indexed logic, address indexed token); + mapping (address => bool) public isFlusher; - /** - * @dev deploy create2 + minimal proxy - * @param owner owner address used for salt - * @param logic flusher contract address - * @param token token address - */ - function deployLogic(address owner, address logic, address token) public returns (address proxy) { + event LogNewProxy(address indexed owner, address indexed logic); + + // deploy create2 + minimal proxy + function deployLogic(address owner, address logic) public returns (address proxy) { + require(!(isFlusherDeployed(getAddress(owner, logic))), "Flusher-already-deployed"); bytes32 salt = keccak256(abi.encodePacked(owner)); bytes20 targetBytes = bytes20(logic); // solium-disable-next-line security/no-inline-assembly assembly { - let clone := mload(0x40) - mstore( - clone, - 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 - ) - mstore(add(clone, 0x14), targetBytes) - mstore( - add(clone, 0x28), - 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000 - ) - proxy := create2(0, clone, 0x37, salt) + let clone := mload(0x40) + mstore( + clone, + 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000 + ) + mstore(add(clone, 0x14), targetBytes) + mstore( + add(clone, 0x28), + 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000 + ) + proxy := create2(0, clone, 0x37, salt) } - IProxy(proxy).setBasic(owner, token); - emit LogNewProxy(owner, logic, token); + isFlusher[proxy] = true; + emit LogNewProxy(owner, logic); } - /** - * @dev compute create2 + minimal proxy address - * @param owner owner address used for salt - * @param logic flusher contract address - */ + function isFlusherDeployed(address _address) public view returns (bool) { + uint32 size; + assembly { + size := extcodesize(_address) + } + return (size > 0); + } + + // compute create2 + minimal proxy address function getAddress(address owner, address logic) public view returns (address) { bytes32 codeHash = keccak256(getCreationCode(logic)); bytes32 salt = keccak256(abi.encodePacked(owner)); @@ -50,14 +48,15 @@ contract Deployer { address(this), salt, codeHash - )); - return address(bytes20(rawAddress << 96)); + ) + ); + return address(bytes20(rawAddress << 96)); } - + function getCreationCode(address logic) public pure returns (bytes memory) { bytes20 a = bytes20(0x3D602d80600A3D3981F3363d3d373d3D3D363d73); bytes20 b = bytes20(logic); bytes15 c = bytes15(0x5af43d82803e903d91602b57fd5bf3); return abi.encodePacked(a, b, c); } -} +} \ No newline at end of file diff --git a/contracts/flusher.sol b/contracts/flusher.sol index 45bc46b..4c0ff58 100644 --- a/contracts/flusher.sol +++ b/contracts/flusher.sol @@ -1,143 +1,41 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.6.8; pragma experimental ABIEncoderV2; -import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; - -interface YieldPool { - function balanceOf(address) external view returns (uint); - function deposit(uint) external payable returns (uint); - function withdraw(uint, address) external returns (uint); -} - interface RegistryInterface { function signer(address) external view returns (bool); - function chief(address) external view returns (bool); - function poolToken(address) external view returns (address); + function isConnector(address[] calldata) external view returns (bool); } contract Flusher { - using SafeERC20 for IERC20; + event LogCast(address indexed sender, uint value); - address payable public owner; + string constant public name = "Flusher-v1"; RegistryInterface public constant registry = RegistryInterface(address(0)); // TODO - Change while deploying. - bool public shield; - uint256 public shieldBlockTime; - uint256 internal waitBlockTime = 172800; // 30 days blocktime. - modifier isSigner { - require(registry.signer(msg.sender), "not-signer"); - _; - } - - modifier isChief { - require(registry.chief(msg.sender), "not-chief"); - _; - } - - event LogInit(address indexed owner); - event LogSwitch(bool indexed shieldState); - event LogDeposit(address indexed token, address indexed tokenPool, uint amount); - event LogWithdraw(address indexed token, address indexed tokenPool,uint amount); - event LogWithdrawToOwner(address indexed token, address indexed owner, uint amount); - - function _deposit(address token) internal { - require(address(token) != address(0), "invalid-token"); - - address poolToken = registry.poolToken(token); - require(poolToken != address(0), "invalid-pool"); - - IERC20 tokenContract = IERC20(token); - - YieldPool poolContract = YieldPool(poolToken); - uint amt; - if (address(tokenContract) == address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)) { - amt = address(this).balance; - poolContract.deposit{value: amt}(amt); - } else { - amt = tokenContract.balanceOf(address(this)); - if (tokenContract.allowance(address(this), address(poolContract)) == 0) - tokenContract.approve(address(poolContract), uint(-1)); - - poolContract.deposit(amt); - } - emit LogDeposit(token, address(poolContract), amt); - } - - function deposit(address token) external payable isSigner { - _deposit(token); - } - - function withdraw(address token, uint amount) external isSigner returns (uint _amount) { - require(address(token) != address(0), "invalid-token"); - address poolToken = registry.poolToken(token); - require(poolToken != address(0), "invalid-pool"); - - _amount = YieldPool(poolToken).withdraw(amount, owner); - emit LogWithdraw(token, poolToken, _amount); - } - - /** - * @dev withdraw to owner (rare case) - */ - function claim(address token) external isSigner returns (uint) { - require(address(token) != address(0), "invalid-token"); - - uint amount; - if (address(token) == address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)) { - amount = address(this).balance; - payable(owner).transfer(amount); - } else { - IERC20 tokenContract = IERC20(token); - amount = tokenContract.balanceOf(address(this)); - tokenContract.safeTransfer(address(owner), amount); - } - emit LogWithdrawToOwner(token, owner, amount); - } - - function setBasic(address newOwner, address token) external { - require(owner == address(0), "already-an-owner"); - require(newOwner != address(0), "not-vaild-owner-address"); - require(token != address(0), "not-vaild-token-address"); - owner = payable(newOwner); - _deposit(token); - emit LogInit(newOwner); - } - - function switchShield() external isChief { - require(registry.chief(msg.sender), "not-chief"); - shield = !shield; - if (!shield) { - shieldBlockTime = block.number + waitBlockTime; - } else { - delete shieldBlockTime; - } - emit LogSwitch(shield); - } - - /** - * @dev backdoor function - */ - function spell(address _target, bytes calldata _data) external isChief { - require(!shield, "shield-access-denied"); - require(shieldBlockTime != 0 && shieldBlockTime <= block.number, "more-than-30-days"); + function spell(address _target, bytes memory _data) internal { require(_target != address(0), "target-invalid"); - require(_data.length > 0, "data-invalid"); - bytes memory _callData = _data; - address _owner = owner; assembly { - let succeeded := delegatecall(gas(), _target, add(_callData, 0x20), mload(_callData), 0, 0) + let succeeded := delegatecall(gas(), _target, add(_data, 0x20), mload(_data), 0, 0) switch iszero(succeeded) - case 1 { - // throw if delegatecall failed - let size := returndatasize() - returndatacopy(0x00, 0x00, size) - revert(0x00, size) - } + case 1 { + let size := returndatasize() + returndatacopy(0x00, 0x00, size) + revert(0x00, size) + } } - require(_owner == owner, "owner-change-denied"); + } + + function cast(address[] calldata _targets, bytes[] calldata _datas) external payable { + require(registry.signer(msg.sender), "not-signer"); + require(_targets.length == _datas.length , "invalid-array-length"); + require(registry.isConnector(_targets), "not-connector"); + for (uint i = 0; i < _targets.length; i++) { + spell(_targets[i], _datas[i]); + } + emit LogCast(msg.sender, msg.value); } receive() external payable {} - -} +} \ No newline at end of file diff --git a/contracts/registry.sol b/contracts/registry.sol index 50d79fc..81da316 100644 --- a/contracts/registry.sol +++ b/contracts/registry.sol @@ -15,6 +15,7 @@ contract Registry { event LogAddSigner(address indexed signer); event LogRemoveSigner(address indexed signer); event LogUpdatePoolLogic(address token, address newLogic); + event LogUpdateFlusherLogic(address token, address newLogic); event LogUpdateFee(address token, uint newFee); event LogUpdateCap(address token, uint newFee); event LogAddPool(address indexed token, address indexed pool); @@ -28,6 +29,7 @@ contract Registry { mapping (address => bool) public signer; mapping (address => address) public poolToken; mapping (address => address) public poolLogic; + mapping (address => address) public flusherLogic; mapping (address => uint) public poolCap; mapping (address => uint) public fee; mapping (address => mapping(address => bool)) public settleLogic; @@ -124,6 +126,20 @@ contract Registry { emit LogUpdatePoolLogic(_pool, _newLogic); } + /** + * @dev update flusher logic + * @param _token pool address + * @param _newLogic new flusher logic address + */ + function updateFlusherLogic(address _token, address _newLogic) external isMaster { + address _pool = poolToken[_token]; + require(_pool != address(0), "invalid-pool"); + require(_newLogic != address(0), "invalid-address"); + require(flusherLogic[_pool] != _newLogic, "same-pool-logic"); + flusherLogic[_pool] = _newLogic; + emit LogUpdateFlusherLogic(_pool, _newLogic); + } + /** * @dev update pool fee * @param _token pool address From 4efb6a2fc74e7f1441ef160a2e3ca267a6fe3e1f Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Mon, 7 Sep 2020 02:41:49 +0530 Subject: [PATCH 07/12] Added missing things from eth pool --- contracts/pools/erc20.sol | 90 +++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/contracts/pools/erc20.sol b/contracts/pools/erc20.sol index 89a4520..5903eb1 100644 --- a/contracts/pools/erc20.sol +++ b/contracts/pools/erc20.sol @@ -16,6 +16,7 @@ interface IndexInterface { interface RegistryInterface { function chief(address) external view returns (bool); function poolLogic(address) external returns (address); + function flusherLogic(address) external returns (address); function fee(address) external view returns (uint); function poolCap(address) external view returns (uint); function checkSettleLogics(address, address[] calldata) external view returns (bool); @@ -25,15 +26,17 @@ interface RateInterface { function getTotalToken() external returns (uint totalUnderlyingTkn); } -contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { +interface FlusherLogicInterface { + function isFlusher(address) external returns (bool); +} + +contract PoolToken is ReentrancyGuard, ERC20Pausable, DSMath { using SafeERC20 for IERC20; - event LogDeploy(address indexed dsa, address token, uint amount); event LogExchangeRate(uint exchangeRate, uint tokenBalance, uint insuranceAmt); event LogSettle(uint settleBlock); event LogDeposit(address indexed user, uint depositAmt, uint poolMintAmt); event LogWithdraw(address indexed user, uint withdrawAmt, uint poolBurnAmt); - event LogAddFee(uint amount); event LogWithdrawFee(uint amount); event LogPausePool(bool); @@ -45,25 +48,30 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { uint public feeAmt; // fee collected on profits constructor( - address _registry, - string memory _name, - string memory _symbol, - address _baseToken + address _registry, + string memory _name, + string memory _symbol, + address _baseToken ) public ERC20(_name, _symbol) { - baseToken = IERC20(_baseToken); - registry = RegistryInterface(_registry); - exchangeRate = 10 ** uint(36 - ERC20(_baseToken).decimals()); + baseToken = IERC20(_baseToken); + registry = RegistryInterface(_registry); + exchangeRate = 10 ** uint(36 - ERC20(_baseToken).decimals()); } modifier isChief() { - require(registry.chief(msg.sender) || msg.sender == instaIndex.master(), "not-chief"); - _; + require(registry.chief(msg.sender) || msg.sender == instaIndex.master(), "not-chief"); + _; + } + + modifier isFlusher() { + require(FlusherLogicInterface(registry.flusherLogic(address(this))).isFlusher(msg.sender), "not-flusher"); + _; } /** * @dev get pool token rate * @param tokenAmt total token amount - */ + */ function getCurrentRate(uint tokenAmt) internal view returns (uint) { return wdiv(totalSupply(), tokenAmt); } @@ -73,26 +81,27 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { */ function setExchangeRate() public { require(msg.sender == address(this), "not-pool-address"); - uint _previousRate = exchangeRate; + uint _prevRate = exchangeRate; uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); _totalToken = sub(_totalToken, feeAmt); - uint _currentRate = getCurrentRate(_totalToken); + uint _newRate = getCurrentRate(_totalToken); uint _tokenBal; - require(_currentRate != 0, "current-rate-is-zero"); - if (_currentRate > _previousRate) { // loss => deduct partially/fully from insurance amount - _currentRate = _previousRate; - } else { // profit => add to insurance amount + require(_newRate != 0, "current-rate-is-zero"); + if (_newRate > _prevRate) { + _newRate = _prevRate; + } else { + _tokenBal = wdiv(totalSupply(), _prevRate); uint _newFee = wmul(sub(_totalToken, _tokenBal), registry.fee(address(this))); feeAmt = add(feeAmt, _newFee); _tokenBal = sub(_totalToken, _newFee); - _currentRate = getCurrentRate(_tokenBal); + _newRate = getCurrentRate(_tokenBal); } - exchangeRate = _currentRate; + exchangeRate = _newRate; emit LogExchangeRate(exchangeRate, _tokenBal, feeAmt); } /** - * @dev Delegate the calls to Connector And this function is ran by cast(). + * @dev delegate the calls to connector and this function is ran by settle() * @param _target Target to of Connector. * @param _data CallData of function in Connector. */ @@ -128,48 +137,48 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { /** * @dev Deposit token. * @param tknAmt token amount - * @return _mintAmt amount of wrap token minted + * @return mintAmt amount of wrap token minted */ - function deposit(uint tknAmt) external whenNotPaused payable returns (uint _mintAmt) { + function deposit(uint tknAmt) public whenNotPaused payable isFlusher returns (uint mintAmt) { require(msg.value == 0, "non-eth-pool"); uint _tokenBal = wdiv(totalSupply(), exchangeRate); uint _newTknBal = add(_tokenBal, tknAmt); require(_newTknBal < registry.poolCap(address(this)), "unmatched-amount"); baseToken.safeTransferFrom(msg.sender, address(this), tknAmt); - _mintAmt = wmul(tknAmt, exchangeRate); - _mint(msg.sender, _mintAmt); - emit LogDeposit(msg.sender, tknAmt, _mintAmt); + mintAmt = wmul(tknAmt, exchangeRate); + _mint(msg.sender, 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 + * @param target withdraw tokens to address + * @return wdAmt amount of token withdrawn */ - function withdraw(uint tknAmt, address to) external nonReentrant whenNotPaused returns (uint _tknAmt) { - require(to != address(0), "to-address-not-vaild"); + function withdraw(uint tknAmt, address target) external nonReentrant whenNotPaused returns (uint wdAmt) { + require(target != address(0), "invalid-target-address"); uint _userBal = wdiv(balanceOf(msg.sender), exchangeRate); uint _burnAmt; if (tknAmt >= _userBal) { _burnAmt = balanceOf(msg.sender); - _tknAmt = _userBal; + wdAmt = _userBal; } else { _burnAmt = wmul(tknAmt, exchangeRate); - _tknAmt = tknAmt; + wdAmt = tknAmt; } - require(_tknAmt <= baseToken.balanceOf(address(this)), "not-enough-liquidity-available"); + require(wdAmt <= baseToken.balanceOf(address(this)), "not-enough-liquidity-available"); _burn(msg.sender, _burnAmt); - baseToken.safeTransfer(to, _tknAmt); + baseToken.safeTransfer(target, wdAmt); - emit LogWithdraw(msg.sender, _tknAmt, _burnAmt); + emit LogWithdraw(msg.sender, wdAmt, _burnAmt); } /** - * @dev Withdraw Insurance from the pool. - * @notice only master can call this function. - * @param wdAmt insurance token amount to remove + * @dev withdraw fee from the pool + * @notice only master can call this function + * @param wdAmt fee amount to withdraw */ function withdrawFee(uint wdAmt) external { require(msg.sender == instaIndex.master(), "not-master"); @@ -189,5 +198,4 @@ contract PoolToken is ReentrancyGuard, DSMath, ERC20Pausable { } receive() external payable {} - -} +} \ No newline at end of file From 71081aaa7b09630ff969d2805fa22a5fa4316272 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Mon, 7 Sep 2020 02:42:03 +0530 Subject: [PATCH 08/12] Added isFlusher for deposit function --- contracts/pools/eth.sol | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/contracts/pools/eth.sol b/contracts/pools/eth.sol index 8dedd21..73dd2c4 100644 --- a/contracts/pools/eth.sol +++ b/contracts/pools/eth.sol @@ -16,6 +16,7 @@ interface IndexInterface { interface RegistryInterface { function chief(address) external view returns (bool); function poolLogic(address) external returns (address); + function flusherLogic(address) external returns (address); function fee(address) external view returns (uint); function poolCap(address) external view returns (uint); function checkSettleLogics(address, address[] calldata) external view returns (bool); @@ -25,6 +26,10 @@ interface RateInterface { function getTotalToken() external returns (uint totalUnderlyingTkn); } +interface FlusherLogicInterface { + function isFlusher(address) external returns (bool); +} + contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { using SafeERC20 for IERC20; @@ -57,6 +62,11 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { _; } + modifier isFlusher() { + require(FlusherLogicInterface(registry.flusherLogic(address(this))).isFlusher(msg.sender), "not-flusher"); + _; + } + /** * @dev get pool token rate * @param tokenAmt total token amount @@ -128,7 +138,7 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { * @param tknAmt token amount * @return mintAmt amount of wrap token minted */ - function deposit(uint tknAmt) public whenNotPaused payable returns (uint mintAmt) { + function deposit(uint tknAmt) public whenNotPaused payable isFlusher returns (uint mintAmt) { require(tknAmt == msg.value, "unmatched-amount"); uint _tokenBal = wdiv(totalSupply(), exchangeRate); uint _newTknBal = add(_tokenBal, tknAmt); From e360235c2493206a480482b42868a2990b1865fd Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Mon, 7 Sep 2020 03:30:20 +0530 Subject: [PATCH 09/12] Minor changes --- contracts/pools/erc20.sol | 10 ++++------ contracts/pools/eth.sol | 8 +++----- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/contracts/pools/erc20.sol b/contracts/pools/erc20.sol index 5903eb1..48523a6 100644 --- a/contracts/pools/erc20.sol +++ b/contracts/pools/erc20.sol @@ -38,7 +38,6 @@ contract PoolToken is ReentrancyGuard, ERC20Pausable, DSMath { event LogDeposit(address indexed user, uint depositAmt, uint poolMintAmt); event LogWithdraw(address indexed user, uint withdrawAmt, uint poolBurnAmt); event LogWithdrawFee(uint amount); - event LogPausePool(bool); IERC20 public immutable baseToken; // Base token. Eg:- DAI, USDC, etc. RegistryInterface public immutable registry; // Pool Registry @@ -77,7 +76,7 @@ contract PoolToken is ReentrancyGuard, ERC20Pausable, DSMath { } /** - * @dev sets exchange rates + * @dev sets exchange rate */ function setExchangeRate() public { require(msg.sender == address(this), "not-pool-address"); @@ -85,12 +84,11 @@ contract PoolToken is ReentrancyGuard, ERC20Pausable, DSMath { uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); _totalToken = sub(_totalToken, feeAmt); uint _newRate = getCurrentRate(_totalToken); - uint _tokenBal; require(_newRate != 0, "current-rate-is-zero"); + uint _tokenBal = wdiv(totalSupply(), _prevRate); if (_newRate > _prevRate) { _newRate = _prevRate; } else { - _tokenBal = wdiv(totalSupply(), _prevRate); uint _newFee = wmul(sub(_totalToken, _tokenBal), registry.fee(address(this))); feeAmt = add(feeAmt, _newFee); _tokenBal = sub(_totalToken, _newFee); @@ -139,11 +137,11 @@ contract PoolToken is ReentrancyGuard, ERC20Pausable, DSMath { * @param tknAmt token amount * @return mintAmt amount of wrap token minted */ - function deposit(uint tknAmt) public whenNotPaused payable isFlusher returns (uint mintAmt) { + function deposit(uint tknAmt) public payable whenNotPaused isFlusher returns (uint mintAmt) { require(msg.value == 0, "non-eth-pool"); uint _tokenBal = wdiv(totalSupply(), exchangeRate); uint _newTknBal = add(_tokenBal, tknAmt); - require(_newTknBal < registry.poolCap(address(this)), "unmatched-amount"); + require(_newTknBal < registry.poolCap(address(this)), "pool-cap-reached"); baseToken.safeTransferFrom(msg.sender, address(this), tknAmt); mintAmt = wmul(tknAmt, exchangeRate); _mint(msg.sender, mintAmt); diff --git a/contracts/pools/eth.sol b/contracts/pools/eth.sol index 73dd2c4..58767c6 100644 --- a/contracts/pools/eth.sol +++ b/contracts/pools/eth.sol @@ -38,7 +38,6 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { event LogDeposit(address indexed user, uint depositAmt, uint poolMintAmt); event LogWithdraw(address indexed user, uint withdrawAmt, uint poolBurnAmt); event LogWithdrawFee(uint amount); - event LogPausePool(bool); IERC20 public immutable baseToken; // Base token. RegistryInterface public immutable registry; // Pool Registry @@ -76,7 +75,7 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { } /** - * @dev sets exchange rates + * @dev sets exchange rate */ function setExchangeRate() public { require(msg.sender == address(this), "not-pool-address"); @@ -84,12 +83,11 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { uint _totalToken = RateInterface(registry.poolLogic(address(this))).getTotalToken(); _totalToken = sub(_totalToken, feeAmt); uint _newRate = getCurrentRate(_totalToken); - uint _tokenBal; require(_newRate != 0, "current-rate-is-zero"); + uint _tokenBal = wdiv(totalSupply(), _prevRate); if (_newRate > _prevRate) { _newRate = _prevRate; } else { - _tokenBal = wdiv(totalSupply(), _prevRate); uint _newFee = wmul(sub(_totalToken, _tokenBal), registry.fee(address(this))); feeAmt = add(feeAmt, _newFee); _tokenBal = sub(_totalToken, _newFee); @@ -142,7 +140,7 @@ contract PoolETH is ReentrancyGuard, ERC20Pausable, DSMath { require(tknAmt == msg.value, "unmatched-amount"); uint _tokenBal = wdiv(totalSupply(), exchangeRate); uint _newTknBal = add(_tokenBal, tknAmt); - require(_newTknBal < registry.poolCap(address(this)), "unmatched-amount"); + require(_newTknBal < registry.poolCap(address(this)), "pool-cap-reached"); mintAmt = wmul(msg.value, exchangeRate); _mint(msg.sender, mintAmt); emit LogDeposit(msg.sender, tknAmt, mintAmt); From a589abfb75867a1c7f159f9deb15981362921b84 Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Mon, 7 Sep 2020 03:35:09 +0530 Subject: [PATCH 10/12] Added connector mapping in registry --- contracts/flusher.sol | 2 ++ contracts/registry.sol | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/contracts/flusher.sol b/contracts/flusher.sol index 4c0ff58..0b2cdbb 100644 --- a/contracts/flusher.sol +++ b/contracts/flusher.sol @@ -12,6 +12,8 @@ contract Flusher { event LogCast(address indexed sender, uint value); string constant public name = "Flusher-v1"; + uint constant version = 1; + RegistryInterface public constant registry = RegistryInterface(address(0)); // TODO - Change while deploying. function spell(address _target, bytes memory _data) internal { diff --git a/contracts/registry.sol b/contracts/registry.sol index 81da316..c428d93 100644 --- a/contracts/registry.sol +++ b/contracts/registry.sol @@ -22,6 +22,8 @@ contract Registry { event LogRemovePool(address indexed token, address indexed pool); event LogAddSettleLogic(address indexed token, address indexed logic); event LogRemoveSettleLogic(address indexed token, address indexed logic); + event LogConnectorEnable(address indexed connector); + event LogConnectorDisable(address indexed connector); IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723); @@ -33,6 +35,7 @@ contract Registry { mapping (address => uint) public poolCap; mapping (address => uint) public fee; mapping (address => mapping(address => bool)) public settleLogic; + mapping(address => bool) public connectors; modifier isMaster() { require(msg.sender == instaIndex.master(), "not-master"); @@ -180,13 +183,37 @@ contract Registry { emit LogRemoveSettleLogic(_pool, _logic); } - function checkSettleLogics(address _pool, address[] calldata _logics) external view returns(bool) { + function enableConnector(address _connector) external isChief { + require(!connectors[_connector], "already-enabled"); + require(_connector != address(0), "invalid-connector"); + connectors[_connector] = true; + emit LogConnectorEnable(_connector); + } + + function disableConnector(address _connector) external isChief { + require(connectors[_connector], "already-disabled"); + delete connectors[_connector]; + emit LogConnectorDisable(_connector); + } + + function checkSettleLogics(address _pool, address[] calldata _logics) external view returns(bool isOk) { + isOk = true; for (uint i = 0; i < _logics.length; i++) { if (!settleLogic[_pool][_logics[i]]) { - return false; + isOk = false; + break; + } + } + } + + function isConnector(address[] calldata _connectors) external view returns (bool isOk) { + isOk = true; + for (uint i = 0; i < _connectors.length; i++) { + if (!connectors[_connectors[i]]) { + isOk = false; + break; } } - return true; } constructor(address _chief) public { From 6676d5a0fb585f96c0d1eecd380290dab05a43fe Mon Sep 17 00:00:00 2001 From: Thrilok Kumar Date: Mon, 7 Sep 2020 03:35:18 +0530 Subject: [PATCH 11/12] minor edit --- contracts/pools/erc20.sol | 1 - contracts/pools/eth.sol | 1 - 2 files changed, 2 deletions(-) diff --git a/contracts/pools/erc20.sol b/contracts/pools/erc20.sol index 48523a6..7fd0c9a 100644 --- a/contracts/pools/erc20.sol +++ b/contracts/pools/erc20.sol @@ -10,7 +10,6 @@ import { DSMath } from "../libs/safeMath.sol"; interface IndexInterface { function master() external view returns (address); - function build(address _owner, uint accountVersion, address _origin) external returns (address _account); } interface RegistryInterface { diff --git a/contracts/pools/eth.sol b/contracts/pools/eth.sol index 58767c6..ba77eee 100644 --- a/contracts/pools/eth.sol +++ b/contracts/pools/eth.sol @@ -10,7 +10,6 @@ import { DSMath } from "../libs/safeMath.sol"; interface IndexInterface { function master() external view returns (address); - function build(address _owner, uint accountVersion, address _origin) external returns (address _account); } interface RegistryInterface { From 051ba623e9710cf8e35eea992dc431325a15c469 Mon Sep 17 00:00:00 2001 From: Sowmay Jain Date: Mon, 7 Sep 2020 14:51:20 +1000 Subject: [PATCH 12/12] done with my changes --- contracts/deployer.sol | 10 +++++----- contracts/flusher.sol | 2 +- contracts/registry.sol | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/contracts/deployer.sol b/contracts/deployer.sol index 5b32762..c1b2cab 100644 --- a/contracts/deployer.sol +++ b/contracts/deployer.sol @@ -3,13 +3,13 @@ pragma solidity ^0.6.8; contract Deployer { - mapping (address => bool) public isFlusher; + mapping (address => bool) public flushers; - event LogNewProxy(address indexed owner, address indexed logic); + event LogNewFlusher(address indexed owner, address indexed flusher, address indexed logic); // deploy create2 + minimal proxy function deployLogic(address owner, address logic) public returns (address proxy) { - require(!(isFlusherDeployed(getAddress(owner, logic))), "Flusher-already-deployed"); + require(!(isFlusherDeployed(getAddress(owner, logic))), "flusher-already-deployed"); bytes32 salt = keccak256(abi.encodePacked(owner)); bytes20 targetBytes = bytes20(logic); // solium-disable-next-line security/no-inline-assembly @@ -26,8 +26,8 @@ contract Deployer { ) proxy := create2(0, clone, 0x37, salt) } - isFlusher[proxy] = true; - emit LogNewProxy(owner, logic); + flushers[proxy] = true; + emit LogNewFlusher(owner, proxy, logic); } function isFlusherDeployed(address _address) public view returns (bool) { diff --git a/contracts/flusher.sol b/contracts/flusher.sol index 0b2cdbb..b14f38b 100644 --- a/contracts/flusher.sol +++ b/contracts/flusher.sol @@ -14,7 +14,7 @@ contract Flusher { string constant public name = "Flusher-v1"; uint constant version = 1; - RegistryInterface public constant registry = RegistryInterface(address(0)); // TODO - Change while deploying. + RegistryInterface public constant registry = RegistryInterface(address(0)); // TODO - Change while deploying function spell(address _target, bytes memory _data) internal { require(_target != address(0), "target-invalid"); diff --git a/contracts/registry.sol b/contracts/registry.sol index c428d93..e3a7e6b 100644 --- a/contracts/registry.sol +++ b/contracts/registry.sol @@ -117,7 +117,7 @@ contract Registry { /** * @dev update pool rate logic - * @param _token pool address + * @param _token token address * @param _newLogic new rate logic address */ function updatePoolLogic(address _token, address _newLogic) external isMaster { @@ -131,7 +131,7 @@ contract Registry { /** * @dev update flusher logic - * @param _token pool address + * @param _token token address * @param _newLogic new flusher logic address */ function updateFlusherLogic(address _token, address _newLogic) external isMaster { @@ -145,7 +145,7 @@ contract Registry { /** * @dev update pool fee - * @param _token pool address + * @param _token token address * @param _newFee new fee amount */ function updateFee(address _token, uint _newFee) external isMaster { @@ -159,7 +159,7 @@ contract Registry { /** * @dev update pool fee - * @param _token pool address + * @param _token token address * @param _newCap new fee amount */ function updateCap(address _token, uint _newCap) external isMaster { @@ -169,6 +169,11 @@ contract Registry { emit LogUpdateCap(_pool, _newCap); } + /** + * @dev adding settlement logic + * @param _token token address + * @param _logic logic proxy + */ function addSettleLogic(address _token, address _logic) external isMaster { address _pool = poolToken[_token]; require(_pool != address(0), "invalid-pool"); @@ -176,6 +181,11 @@ contract Registry { emit LogAddSettleLogic(_pool, _logic); } + /** + * @dev removing settlement logic + * @param _token token address + * @param _logic logic proxy + */ function removeSettleLogic(address _token, address _logic) external isMaster { address _pool = poolToken[_token]; require(_pool != address(0), "invalid-pool"); @@ -183,6 +193,10 @@ contract Registry { emit LogRemoveSettleLogic(_pool, _logic); } + /** + * @dev enable pool connector + * @param _connector logic proxy + */ function enableConnector(address _connector) external isChief { require(!connectors[_connector], "already-enabled"); require(_connector != address(0), "invalid-connector"); @@ -190,12 +204,20 @@ contract Registry { emit LogConnectorEnable(_connector); } + /** + * @dev disable pool connector + * @param _connector logic proxy + */ function disableConnector(address _connector) external isChief { require(connectors[_connector], "already-disabled"); delete connectors[_connector]; emit LogConnectorDisable(_connector); } + /** + * @dev disable pool connector + * @param _connector logic proxy + */ function checkSettleLogics(address _pool, address[] calldata _logics) external view returns(bool isOk) { isOk = true; for (uint i = 0; i < _logics.length; i++) { @@ -206,6 +228,10 @@ contract Registry { } } + /** + * @dev check if connectors are enabled + * @param _connectors array of logic proxy + */ function isConnector(address[] calldata _connectors) external view returns (bool isOk) { isOk = true; for (uint i = 0; i < _connectors.length; i++) {