diff --git a/contracts/MemberSystem/impl/MemAggregator.sol b/contracts/MemberSystem/impl/MemAggregator.sol new file mode 100644 index 0000000..e519cd8 --- /dev/null +++ b/contracts/MemberSystem/impl/MemAggregator.sol @@ -0,0 +1,57 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + +import {Ownable} from "../../lib/Ownable.sol"; +import {SafeMath} from "../../lib/SafeMath.sol"; +import {DecimalMath} from "../../lib/DecimalMath.sol"; + +interface IMemSource { + function getMemLevel(address user) external returns (uint256); +} + +contract MemRegistry is Ownable { + using SafeMath for uint256; + + address[] internal _VALID_MEM_SOURCE_LIST_; + mapping(address => bool) internal _VALID_MEM_SOURCE_; + mapping(address => uint256) internal _MEM_SOURCE_WEIGHT_; + + function getMemLevel(address user) public returns (uint256 memLevel) { + for (uint8 i = 0; i < _VALID_MEM_SOURCE_LIST_.length; i++) { + address _source = _VALID_MEM_SOURCE_LIST_[i]; + memLevel = memLevel.add( + IMemSource(_source).getMemLevel(user).mul(_MEM_SOURCE_WEIGHT_[_source]) + ); + } + } + + function setMemSourceWeight(address source, uint256 weight) external onlyOwner { + _MEM_SOURCE_WEIGHT_[source] = weight; + } + + function addMemSource(address source) external onlyOwner { + require(!_VALID_MEM_SOURCE_[source], "SOURCE_ALREADY_EXIST"); + _VALID_MEM_SOURCE_LIST_.push(source); + _VALID_MEM_SOURCE_[source] = true; + } + + function removeMemSource(address source) external onlyOwner { + require(_VALID_MEM_SOURCE_[source], "SOURCE_NOT_EXIST"); + for (uint8 i = 0; i <= _VALID_MEM_SOURCE_LIST_.length - 1; i++) { + if (_VALID_MEM_SOURCE_LIST_[i] == source) { + _VALID_MEM_SOURCE_LIST_[i] = _VALID_MEM_SOURCE_LIST_[_VALID_MEM_SOURCE_LIST_ + .length - 1]; + _VALID_MEM_SOURCE_LIST_.pop(); + break; + } + } + _VALID_MEM_SOURCE_[source] = false; + } +} diff --git a/contracts/MemberSystem/impl/MemSourceStake.sol b/contracts/MemberSystem/impl/MemSourceStake.sol new file mode 100644 index 0000000..6a2cb50 --- /dev/null +++ b/contracts/MemberSystem/impl/MemSourceStake.sol @@ -0,0 +1,85 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + +import {Ownable} from "../../lib/Ownable.sol"; +import {IMemSource} from "./MemAggregator.sol"; +import {IERC20} from "../../intf/IERC20.sol"; +import {SafeMath} from "../../lib/SafeMath.sol"; +import {SafeERC20} from "../../lib/SafeERC20.sol"; +import {DecimalMath} from "../../lib/DecimalMath.sol"; + +contract MemSourceStake is Ownable, IMemSource { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + address public _DODO_TOKEN_; + uint256 public _DODO_RESERVE_; + uint256 public _COLD_DOWN_DURATION_; + + mapping(address => uint256) internal _STAKED_DODO_; + mapping(address => uint256) internal _PENDING_DODO_; + mapping(address => uint256) internal _EXECUTE_TIME_; + + constructor(address dodoToken) public { + _DODO_TOKEN_ = dodoToken; + } + + // ============ Owner Function ============ + + function setColdDownDuration(uint256 coldDownDuration) external onlyOwner { + _COLD_DOWN_DURATION_ = coldDownDuration; + } + + // ============ DODO Function ============ + + function admitStakedDODO(address to) external { + uint256 dodoInput = IERC20(_DODO_TOKEN_).balanceOf(address(this)).sub(_DODO_RESERVE_); + _STAKED_DODO_[to] = _STAKED_DODO_[to].add(dodoInput); + _sync(); + } + + function stakeDODO(uint256 amount) external { + _transferDODOIn(msg.sender, amount); + _STAKED_DODO_[msg.sender] = _STAKED_DODO_[msg.sender].add(amount); + _sync(); + } + + function requestDODOWithdraw(uint256 amount) external { + _STAKED_DODO_[msg.sender] = _STAKED_DODO_[msg.sender].sub(amount); + _PENDING_DODO_[msg.sender] = _PENDING_DODO_[msg.sender].add(amount); + _EXECUTE_TIME_[msg.sender] = block.timestamp.add(_COLD_DOWN_DURATION_); + } + + function withdrawDODO() external { + require(_EXECUTE_TIME_[msg.sender] <= block.timestamp, "WITHDRAW_COLD_DOWN"); + _transferDODOOut(msg.sender, _PENDING_DODO_[msg.sender]); + _PENDING_DODO_[msg.sender] = 0; + } + + // ============ Balance Function ============ + + function _transferDODOIn(address from, uint256 amount) internal { + IERC20(_DODO_TOKEN_).transferFrom(from, address(this), amount); + } + + function _transferDODOOut(address to, uint256 amount) internal { + IERC20(_DODO_TOKEN_).transfer(to, amount); + } + + function _sync() internal { + _DODO_RESERVE_ = IERC20(_DODO_TOKEN_).balanceOf(address(this)); + } + + // ============ View Function ============ + + function getMemLevel(address user) external override returns (uint256) { + return _STAKED_DODO_[user]; + } +}