文件 1 的 1:DODOCpProxy.sol
pragma solidity 0.6.9;
interface IDODOApprove {
function claimTokens(address token,address who,address dest,uint256 amount) external;
function getDODOProxy() external view returns (address);
}
contract InitializableOwnable {
address public _OWNER_;
address public _NEW_OWNER_;
bool internal _INITIALIZED_;
event OwnershipTransferPrepared(address indexed previousOwner, address indexed newOwner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
modifier notInitialized() {
require(!_INITIALIZED_, "DODO_INITIALIZED");
_;
}
modifier onlyOwner() {
require(msg.sender == _OWNER_, "NOT_OWNER");
_;
}
function initOwner(address newOwner) public notInitialized {
_INITIALIZED_ = true;
_OWNER_ = newOwner;
}
function transferOwnership(address newOwner) public onlyOwner {
emit OwnershipTransferPrepared(_OWNER_, newOwner);
_NEW_OWNER_ = newOwner;
}
function claimOwnership() public {
require(msg.sender == _NEW_OWNER_, "INVALID_CLAIM");
emit OwnershipTransferred(_OWNER_, _NEW_OWNER_);
_OWNER_ = _NEW_OWNER_;
_NEW_OWNER_ = address(0);
}
}
interface IDODOApproveProxy {
function isAllowedProxy(address _proxy) external view returns (bool);
function claimTokens(address token,address who,address dest,uint256 amount) external;
}
contract DODOApproveProxy is InitializableOwnable {
uint256 private constant _TIMELOCK_DURATION_ = 3 days;
mapping (address => bool) public _IS_ALLOWED_PROXY_;
uint256 public _TIMELOCK_;
address public _PENDING_ADD_DODO_PROXY_;
address public immutable _DODO_APPROVE_;
modifier notLocked() {
require(
_TIMELOCK_ <= block.timestamp,
"SetProxy is timelocked"
);
_;
}
constructor(address dodoApporve) public {
_DODO_APPROVE_ = dodoApporve;
}
function init(address owner, address[] memory proxies) external {
initOwner(owner);
for(uint i = 0; i < proxies.length; i++)
_IS_ALLOWED_PROXY_[proxies[i]] = true;
}
function unlockAddProxy(address newDodoProxy) public onlyOwner {
_TIMELOCK_ = block.timestamp + _TIMELOCK_DURATION_;
_PENDING_ADD_DODO_PROXY_ = newDodoProxy;
}
function lockAddProxy() public onlyOwner {
_PENDING_ADD_DODO_PROXY_ = address(0);
_TIMELOCK_ = 0;
}
function addDODOProxy() external onlyOwner notLocked() {
_IS_ALLOWED_PROXY_[_PENDING_ADD_DODO_PROXY_] = true;
lockAddProxy();
}
function removeDODOProxy (address oldDodoProxy) public onlyOwner {
_IS_ALLOWED_PROXY_[oldDodoProxy] = false;
}
function claimTokens(
address token,
address who,
address dest,
uint256 amount
) external {
require(_IS_ALLOWED_PROXY_[msg.sender], "DODOApproveProxy:Access restricted");
IDODOApprove(_DODO_APPROVE_).claimTokens(
token,
who,
dest,
amount
);
}
function isAllowedProxy(address _proxy) external view returns (bool) {
return _IS_ALLOWED_PROXY_[_proxy];
}
}
interface IDODOV2 {
function sellBase(address to) external returns (uint256 receiveQuoteAmount);
function sellQuote(address to) external returns (uint256 receiveBaseAmount);
function getVaultReserve() external view returns (uint256 baseReserve, uint256 quoteReserve);
function _BASE_TOKEN_() external view returns (address);
function _QUOTE_TOKEN_() external view returns (address);
function getPMMStateForCall() external view returns (
uint256 i,
uint256 K,
uint256 B,
uint256 Q,
uint256 B0,
uint256 Q0,
uint256 R
);
function getUserFeeRate(address user) external view returns (uint256 lpFeeRate, uint256 mtFeeRate);
function getDODOPoolBidirection(address token0, address token1) external view returns (address[] memory, address[] memory);
function createDODOVendingMachine(
address baseToken,
address quoteToken,
uint256 lpFeeRate,
uint256 i,
uint256 k,
bool isOpenTWAP
) external returns (address newVendingMachine);
function buyShares(address to) external returns (uint256,uint256,uint256);
function createDODOPrivatePool() external returns (address newPrivatePool);
function initDODOPrivatePool(
address dppAddress,
address creator,
address baseToken,
address quoteToken,
uint256 lpFeeRate,
uint256 k,
uint256 i,
bool isOpenTwap
) external;
function reset(
address operator,
uint256 newLpFeeRate,
uint256 newI,
uint256 newK,
uint256 baseOutAmount,
uint256 quoteOutAmount,
uint256 minBaseReserve,
uint256 minQuoteReserve
) external returns (bool);
function _OWNER_() external returns (address);
function createCrowdPooling() external returns (address payable newCrowdPooling);
function initCrowdPooling(
address cpAddress,
address creator,
address[] memory tokens,
uint256[] memory timeLine,
uint256[] memory valueList,
bool[] memory switches
) external;
function bid(address to) external;
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function decimals() external view returns (uint8);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
}
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "MUL_ERROR");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "DIVIDING_ERROR");
return a / b;
}
function divCeil(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 quotient = div(a, b);
uint256 remainder = a - quotient * b;
if (remainder > 0) {
return quotient + 1;
} else {
return quotient;
}
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SUB_ERROR");
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "ADD_ERROR");
return c;
}
function sqrt(uint256 x) internal pure returns (uint256 y) {
uint256 z = x / 2 + 1;
y = x;
while (z < y) {
y = z;
z = (x / z + z) / 2;
}
}
}
library SafeERC20 {
using SafeMath for uint256;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(
token,
abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
);
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
interface IWETH {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address src,
address dst,
uint256 wad
) external returns (bool);
function deposit() external payable;
function withdraw(uint256 wad) external;
}
contract ReentrancyGuard {
bool private _ENTERED_;
modifier preventReentrant() {
require(!_ENTERED_, "REENTRANT");
_ENTERED_ = true;
_;
_ENTERED_ = false;
}
}
contract DODOCpProxy is ReentrancyGuard {
using SafeMath for uint256;
using SafeERC20 for IERC20;
address constant _ETH_ADDRESS_ = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address public immutable _WETH_;
address public immutable _DODO_APPROVE_PROXY_;
address public immutable _CP_FACTORY_;
modifier judgeExpired(uint256 deadLine) {
require(deadLine >= block.timestamp, "DODOCpProxy: EXPIRED");
_;
}
fallback() external payable {}
receive() external payable {}
constructor(
address payable weth,
address cpFactory,
address dodoApproveProxy
) public {
_WETH_ = weth;
_CP_FACTORY_ = cpFactory;
_DODO_APPROVE_PROXY_ = dodoApproveProxy;
}
function createCrowdPooling(
address baseToken,
address quoteToken,
uint256 baseInAmount,
uint256[] memory timeLine,
uint256[] memory valueList,
bool[] memory switches,
uint256 deadLine
) external payable preventReentrant judgeExpired(deadLine) returns (address payable newCrowdPooling) {
address _baseToken = baseToken;
address _quoteToken = quoteToken == _ETH_ADDRESS_ ? _WETH_ : quoteToken;
newCrowdPooling = IDODOV2(_CP_FACTORY_).createCrowdPooling();
_deposit(
msg.sender,
newCrowdPooling,
_baseToken,
baseInAmount,
false
);
(bool success, ) = newCrowdPooling.call{value: msg.value}("");
require(success, "DODOCpProxy: Transfer failed");
address[] memory tokens = new address[](2);
tokens[0] = _baseToken;
tokens[1] = _quoteToken;
IDODOV2(_CP_FACTORY_).initCrowdPooling(
newCrowdPooling,
msg.sender,
tokens,
timeLine,
valueList,
switches
);
}
function bid(
address cpAddress,
uint256 quoteAmount,
uint8 flag,
uint256 deadLine
) external payable preventReentrant judgeExpired(deadLine) {
_deposit(msg.sender, cpAddress, IDODOV2(cpAddress)._QUOTE_TOKEN_(), quoteAmount, flag == 1);
IDODOV2(cpAddress).bid(msg.sender);
}
function _deposit(
address from,
address to,
address token,
uint256 amount,
bool isETH
) internal {
if (isETH) {
if (amount > 0) {
require(msg.value == amount, "ETH_VALUE_WRONG");
IWETH(_WETH_).deposit{value: amount}();
if (to != address(this)) SafeERC20.safeTransfer(IERC20(_WETH_), to, amount);
}
} else {
IDODOApproveProxy(_DODO_APPROVE_PROXY_).claimTokens(token, from, to, amount);
}
}
}