diff --git a/contracts/helper/ChainlinkCOMPUSDCPriceOracleProxy.sol b/contracts/helper/ChainlinkCOMPUSDCPriceOracleProxy.sol new file mode 100644 index 0000000..6f9bce8 --- /dev/null +++ b/contracts/helper/ChainlinkCOMPUSDCPriceOracleProxy.sol @@ -0,0 +1,25 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + + +interface IChainlink { + function latestAnswer() external view returns (uint256); +} + + +// for COMP-USDC(decimals=6) price convert + +contract ChainlinkCOMPUSDCPriceOracleProxy { + address public chainlink = 0xdbd020CAeF83eFd542f4De03e3cF0C28A4428bd5; + + function getPrice() external view returns (uint256) { + return IChainlink(chainlink).latestAnswer() / 100; + } +} diff --git a/contracts/helper/ChainlinkEthPriceOracleProxy.sol b/contracts/helper/ChainlinkEthPriceOracleProxy.sol index 47a6852..53036a7 100644 --- a/contracts/helper/ChainlinkEthPriceOracleProxy.sol +++ b/contracts/helper/ChainlinkEthPriceOracleProxy.sol @@ -8,14 +8,16 @@ pragma solidity 0.6.9; pragma experimental ABIEncoderV2; + interface IChainlink { function latestAnswer() external view returns (uint256); } + // for WETH-USDC(decimals=6) price convert contract ChainlinkETHPriceOracleProxy { - address public chainlink = 0xF79D6aFBb6dA890132F9D7c355e3015f15F3406F; + address public chainlink = 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419; function getPrice() external view returns (uint256) { return IChainlink(chainlink).latestAnswer() / 100; diff --git a/contracts/helper/ChainlinkLENDUSDCPriceOracleProxy.sol b/contracts/helper/ChainlinkLENDUSDCPriceOracleProxy.sol new file mode 100644 index 0000000..c338136 --- /dev/null +++ b/contracts/helper/ChainlinkLENDUSDCPriceOracleProxy.sol @@ -0,0 +1,25 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + + +interface IChainlink { + function latestAnswer() external view returns (uint256); +} + + +// for LEND-USDC(decimals=6) price convert + +contract ChainlinkLENDUSDCPriceOracleProxy { + address public chainlink = 0x4aB81192BB75474Cf203B56c36D6a13623270A67; + + function getPrice() external view returns (uint256) { + return IChainlink(chainlink).latestAnswer() / 100; + } +} diff --git a/contracts/helper/ChainlinkLINKUSDPriceOracleProxy.sol b/contracts/helper/ChainlinkLINKUSDPriceOracleProxy.sol new file mode 100644 index 0000000..fe6615d --- /dev/null +++ b/contracts/helper/ChainlinkLINKUSDPriceOracleProxy.sol @@ -0,0 +1,25 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + + +interface IChainlink { + function latestAnswer() external view returns (uint256); +} + + +// for LINK-USDC(decimals=6) price convert + +contract ChainlinkLINKUSDCPriceOracleProxy { + address public chainlink = 0x2c1d072e956AFFC0D435Cb7AC38EF18d24d9127c; + + function getPrice() external view returns (uint256) { + return IChainlink(chainlink).latestAnswer() / 100; + } +} diff --git a/contracts/helper/ChainlinkSNXUSDPriceOracleProxy.sol b/contracts/helper/ChainlinkSNXUSDPriceOracleProxy.sol new file mode 100644 index 0000000..e3d478c --- /dev/null +++ b/contracts/helper/ChainlinkSNXUSDPriceOracleProxy.sol @@ -0,0 +1,25 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + + +interface IChainlink { + function latestAnswer() external view returns (uint256); +} + + +// for SNX-USDC(decimals=6) price convert + +contract ChainlinkSNXUSDCPriceOracleProxy { + address public chainlink = 0xDC3EA94CD0AC27d9A86C180091e7f78C683d3699; + + function getPrice() external view returns (uint256) { + return IChainlink(chainlink).latestAnswer() / 100; + } +} diff --git a/contracts/helper/ChainlinkWBTCUSDCPriceOracleProxy.sol b/contracts/helper/ChainlinkWBTCUSDCPriceOracleProxy.sol new file mode 100644 index 0000000..ae78ebd --- /dev/null +++ b/contracts/helper/ChainlinkWBTCUSDCPriceOracleProxy.sol @@ -0,0 +1,25 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + + +interface IChainlink { + function latestAnswer() external view returns (uint256); +} + + +// for WBTC(decimals=8)-USDC(decimals=6) price convert + +contract ChainlinkWBTCUSDCPriceOracleProxy { + address public chainlink = 0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c; + + function getPrice() external view returns (uint256) { + return IChainlink(chainlink).latestAnswer() * (10**8); + } +} diff --git a/contracts/helper/MinimumOracle.sol b/contracts/helper/MinimumOracle.sol new file mode 100644 index 0000000..0056add --- /dev/null +++ b/contracts/helper/MinimumOracle.sol @@ -0,0 +1,56 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + + +interface IMinimumOracle { + function getPrice() external view returns (uint256); + + function setPrice(uint256 newPrice) external; + + function transferOwnership(address newOwner) external; +} + + +contract MinimumOracle { + address public _OWNER_; + uint256 public tokenPrice; + + // ============ Events ============ + + event OwnershipTransfer(address indexed previousOwner, address indexed newOwner); + + // ============ Modifiers ============ + + modifier onlyOwner() { + require(msg.sender == _OWNER_, "NOT_OWNER"); + _; + } + + // ============ Functions ============ + + constructor() public { + _OWNER_ = msg.sender; + emit OwnershipTransfer(address(0), _OWNER_); + } + + function transferOwnership(address newOwner) external onlyOwner { + require(newOwner != address(0), "INVALID_OWNER"); + emit OwnershipTransfer(_OWNER_, newOwner); + _OWNER_ = newOwner; + } + + function setPrice(uint256 newPrice) external onlyOwner { + tokenPrice = newPrice; + } + + function getPrice() external view returns (uint256) { + return tokenPrice; + } +} diff --git a/contracts/helper/MultiSigWalletWithTimeLock.sol b/contracts/helper/MultiSigWalletWithTimeLock.sol deleted file mode 100644 index 28af423..0000000 --- a/contracts/helper/MultiSigWalletWithTimeLock.sol +++ /dev/null @@ -1,423 +0,0 @@ -/** - *Submitted for verification at Etherscan.io on 2019-10-15 - */ - -/* - - Copyright 2019 The Hydro Protocol Foundation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity 0.5.8; -pragma experimental ABIEncoderV2; - -contract MultiSigWalletWithTimelock { - uint256 public constant MAX_OWNER_COUNT = 50; - uint256 public lockSeconds = 86400; - - event Confirmation(address indexed sender, uint256 indexed transactionId); - event Revocation(address indexed sender, uint256 indexed transactionId); - event Submission(uint256 indexed transactionId); - event Execution(uint256 indexed transactionId); - event ExecutionFailure(uint256 indexed transactionId); - event Deposit(address indexed sender, uint256 value); - event OwnerAddition(address indexed owner); - event OwnerRemoval(address indexed owner); - event RequirementChange(uint256 required); - event UnlockTimeSet(uint256 indexed transactionId, uint256 confirmationTime); - event LockSecondsChange(uint256 lockSeconds); - - mapping(uint256 => Transaction) public transactions; - mapping(uint256 => mapping(address => bool)) public confirmations; - mapping(address => bool) public isOwner; - mapping(uint256 => uint256) public unlockTimes; - - address[] public owners; - uint256 public required; - uint256 public transactionCount; - - struct Transaction { - address destination; - uint256 value; - bytes data; - bool executed; - } - - struct EmergencyCall { - bytes32 selector; - uint256 paramsBytesCount; - } - - // Functions bypass the time lock process - EmergencyCall[] public emergencyCalls; - - modifier onlyWallet() { - if (msg.sender != address(this)) revert("ONLY_WALLET_ERROR"); - _; - } - - modifier ownerDoesNotExist(address owner) { - if (isOwner[owner]) revert("OWNER_DOES_NOT_EXIST_ERROR"); - _; - } - - modifier ownerExists(address owner) { - if (!isOwner[owner]) revert("OWNER_EXISTS_ERROR"); - _; - } - - modifier transactionExists(uint256 transactionId) { - if (transactions[transactionId].destination == address(0)) - revert("TRANSACTION_EXISTS_ERROR"); - _; - } - - modifier confirmed(uint256 transactionId, address owner) { - if (!confirmations[transactionId][owner]) revert("CONFIRMED_ERROR"); - _; - } - - modifier notConfirmed(uint256 transactionId, address owner) { - if (confirmations[transactionId][owner]) revert("NOT_CONFIRMED_ERROR"); - _; - } - - modifier notExecuted(uint256 transactionId) { - if (transactions[transactionId].executed) revert("NOT_EXECUTED_ERROR"); - _; - } - - modifier notNull(address _address) { - if (_address == address(0)) revert("NOT_NULL_ERROR"); - _; - } - - modifier validRequirement(uint256 ownerCount, uint256 _required) { - if ( - ownerCount > MAX_OWNER_COUNT || - _required > ownerCount || - _required == 0 || - ownerCount == 0 - ) revert("VALID_REQUIREMENT_ERROR"); - _; - } - - /** @dev Fallback function allows to deposit ether. */ - function() external payable { - if (msg.value > 0) { - emit Deposit(msg.sender, msg.value); - } - } - - /** @dev Contract constructor sets initial owners and required number of confirmations. - * @param _owners List of initial owners. - * @param _required Number of required confirmations. - */ - constructor(address[] memory _owners, uint256 _required) - public - validRequirement(_owners.length, _required) - { - for (uint256 i = 0; i < _owners.length; i++) { - if (isOwner[_owners[i]] || _owners[i] == address(0)) { - revert("OWNER_ERROR"); - } - - isOwner[_owners[i]] = true; - } - - owners = _owners; - required = _required; - - // initialzie Emergency calls - emergencyCalls.push( - EmergencyCall({ - selector: keccak256(abi.encodePacked("setMarketBorrowUsability(uint16,bool)")), - paramsBytesCount: 64 - }) - ); - } - - function getEmergencyCallsCount() external view returns (uint256 count) { - return emergencyCalls.length; - } - - /** @dev Allows to add a new owner. Transaction has to be sent by wallet. - * @param owner Address of new owner. - */ - function addOwner(address owner) - external - onlyWallet - ownerDoesNotExist(owner) - notNull(owner) - validRequirement(owners.length + 1, required) - { - isOwner[owner] = true; - owners.push(owner); - emit OwnerAddition(owner); - } - - /** @dev Allows to remove an owner. Transaction has to be sent by wallet. - * @param owner Address of owner. - */ - function removeOwner(address owner) external onlyWallet ownerExists(owner) { - isOwner[owner] = false; - for (uint256 i = 0; i < owners.length - 1; i++) { - if (owners[i] == owner) { - owners[i] = owners[owners.length - 1]; - break; - } - } - - owners.length -= 1; - - if (required > owners.length) { - changeRequirement(owners.length); - } - - emit OwnerRemoval(owner); - } - - /** @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet. - * @param owner Address of owner to be replaced. - * @param owner Address of new owner. - */ - function replaceOwner(address owner, address newOwner) - external - onlyWallet - ownerExists(owner) - ownerDoesNotExist(newOwner) - { - for (uint256 i = 0; i < owners.length; i++) { - if (owners[i] == owner) { - owners[i] = newOwner; - break; - } - } - - isOwner[owner] = false; - isOwner[newOwner] = true; - emit OwnerRemoval(owner); - emit OwnerAddition(newOwner); - } - - /** @dev Allows to change the number of required confirmations. Transaction has to be sent by wallet. - * @param _required Number of required confirmations. - */ - function changeRequirement(uint256 _required) - public - onlyWallet - validRequirement(owners.length, _required) - { - required = _required; - emit RequirementChange(_required); - } - - /** @dev Changes the duration of the time lock for transactions. - * @param _lockSeconds Duration needed after a transaction is confirmed and before it becomes executable, in seconds. - */ - function changeLockSeconds(uint256 _lockSeconds) external onlyWallet { - lockSeconds = _lockSeconds; - emit LockSecondsChange(_lockSeconds); - } - - /** @dev Allows an owner to submit and confirm a transaction. - * @param destination Transaction target address. - * @param value Transaction ether value. - * @param data Transaction data payload. - * @return Returns transaction ID. - */ - function submitTransaction( - address destination, - uint256 value, - bytes calldata data - ) external ownerExists(msg.sender) notNull(destination) returns (uint256 transactionId) { - transactionId = transactionCount; - transactions[transactionId] = Transaction({ - destination: destination, - value: value, - data: data, - executed: false - }); - transactionCount += 1; - emit Submission(transactionId); - confirmTransaction(transactionId); - } - - /** @dev Allows an owner to confirm a transaction. - * @param transactionId Transaction ID. - */ - function confirmTransaction(uint256 transactionId) - public - ownerExists(msg.sender) - transactionExists(transactionId) - notConfirmed(transactionId, msg.sender) - { - confirmations[transactionId][msg.sender] = true; - emit Confirmation(msg.sender, transactionId); - - if ( - isConfirmed(transactionId) && - unlockTimes[transactionId] == 0 && - !isEmergencyCall(transactionId) - ) { - uint256 unlockTime = block.timestamp + lockSeconds; - unlockTimes[transactionId] = unlockTime; - emit UnlockTimeSet(transactionId, unlockTime); - } - } - - function isEmergencyCall(uint256 transactionId) internal view returns (bool) { - bytes memory data = transactions[transactionId].data; - - for (uint256 i = 0; i < emergencyCalls.length; i++) { - EmergencyCall memory emergencyCall = emergencyCalls[i]; - - if ( - data.length == emergencyCall.paramsBytesCount + 4 && - data.length >= 4 && - emergencyCall.selector[0] == data[0] && - emergencyCall.selector[1] == data[1] && - emergencyCall.selector[2] == data[2] && - emergencyCall.selector[3] == data[3] - ) { - return true; - } - } - - return false; - } - - /** @dev Allows an owner to revoke a confirmation for a transaction. - * @param transactionId Transaction ID. - */ - function revokeConfirmation(uint256 transactionId) - external - ownerExists(msg.sender) - confirmed(transactionId, msg.sender) - notExecuted(transactionId) - { - confirmations[transactionId][msg.sender] = false; - emit Revocation(msg.sender, transactionId); - } - - /** @dev Allows anyone to execute a confirmed transaction. - * @param transactionId Transaction ID. - */ - function executeTransaction(uint256 transactionId) - external - ownerExists(msg.sender) - notExecuted(transactionId) - { - require(block.timestamp >= unlockTimes[transactionId], "TRANSACTION_NEED_TO_UNLOCK"); - - if (isConfirmed(transactionId)) { - Transaction storage transaction = transactions[transactionId]; - transaction.executed = true; - (bool success, ) = transaction.destination.call.value(transaction.value)( - transaction.data - ); - if (success) emit Execution(transactionId); - else { - emit ExecutionFailure(transactionId); - transaction.executed = false; - } - } - } - - /** @dev Returns the confirmation status of a transaction. - * @param transactionId Transaction ID. - * @return Confirmation status. - */ - function isConfirmed(uint256 transactionId) public view returns (bool) { - uint256 count = 0; - - for (uint256 i = 0; i < owners.length; i++) { - if (confirmations[transactionId][owners[i]]) { - count += 1; - } - - if (count >= required) { - return true; - } - } - - return false; - } - - /* Web3 call functions */ - - /** @dev Returns number of confirmations of a transaction. - * @param transactionId Transaction ID. - * @return Number of confirmations. - */ - function getConfirmationCount(uint256 transactionId) external view returns (uint256 count) { - for (uint256 i = 0; i < owners.length; i++) { - if (confirmations[transactionId][owners[i]]) { - count += 1; - } - } - } - - /** @dev Returns total number of transactions after filers are applied. - * @param pending Include pending transactions. - * @param executed Include executed transactions. - * @return Total number of transactions after filters are applied. - */ - function getTransactionCount(bool pending, bool executed) - external - view - returns (uint256 count) - { - for (uint256 i = 0; i < transactionCount; i++) { - if ((pending && !transactions[i].executed) || (executed && transactions[i].executed)) { - count += 1; - } - } - } - - /** @dev Returns list of owners. - * @return List of owner addresses. - */ - function getOwners() external view returns (address[] memory) { - return owners; - } - - /** @dev Returns array with owner addresses, which confirmed transaction. - * @param transactionId Transaction ID. - * @return Returns array of owner addresses. - */ - function getConfirmations(uint256 transactionId) - external - view - returns (address[] memory _confirmations) - { - address[] memory confirmationsTemp = new address[](owners.length); - uint256 count = 0; - uint256 i; - - for (i = 0; i < owners.length; i++) { - if (confirmations[transactionId][owners[i]]) { - confirmationsTemp[count] = owners[i]; - count += 1; - } - } - - _confirmations = new address[](count); - - for (i = 0; i < count; i++) { - _confirmations[i] = confirmationsTemp[i]; - } - } -}