编译器
0.6.12+commit.27d51765
文件 1 的 58:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 58:AggregatorV3Interface.sol
pragma solidity >=0.6.0;
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
function getRoundData(uint80 _roundId)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
文件 3 的 58:CollectableDust.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/EnumerableSet.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../Interfaces/Keep3r/ICollectableDust.sol";
abstract contract CollectableDust is ICollectableDust {
using EnumerableSet for EnumerableSet.AddressSet;
address public constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
EnumerableSet.AddressSet internal protocolTokens;
constructor() public {}
function _addProtocolToken(address _token) internal {
require(!protocolTokens.contains(_token), "collectable-dust::token-is-part-of-the-protocol");
protocolTokens.add(_token);
}
function _removeProtocolToken(address _token) internal {
require(protocolTokens.contains(_token), "collectable-dust::token-not-part-of-the-protocol");
protocolTokens.remove(_token);
}
function _sendDust(
address _to,
address _token,
uint256 _amount
) internal {
require(_to != address(0), "collectable-dust::cant-send-dust-to-zero-address");
require(!protocolTokens.contains(_token), "collectable-dust::token-is-part-of-the-protocol");
if (_token == ETH_ADDRESS) {
payable(_to).transfer(_amount);
} else {
IERC20(_token).transfer(_to, _amount);
}
emit DustSent(_to, _token, _amount);
}
}
文件 4 的 58:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 5 的 58:Counters.sol
pragma solidity >=0.6.0 <0.8.0;
import "../math/SafeMath.sol";
library Counters {
using SafeMath for uint256;
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value.sub(1);
}
}
文件 6 的 58:ERC165.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
mapping(bytes4 => bool) private _supportedInterfaces;
constructor () internal {
_registerInterface(_INTERFACE_ID_ERC165);
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return _supportedInterfaces[interfaceId];
}
function _registerInterface(bytes4 interfaceId) internal virtual {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}
文件 7 的 58:ERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
constructor (string memory name_, string memory symbol_) public {
_name = name_;
_symbol = symbol_;
_decimals = 18;
}
function name() public view virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return _decimals;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _setupDecimals(uint8 decimals_) internal virtual {
_decimals = decimals_;
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
文件 8 的 58:ERC721.sol
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/Context.sol";
import "./IERC721.sol";
import "./IERC721Metadata.sol";
import "./IERC721Enumerable.sol";
import "./IERC721Receiver.sol";
import "../../introspection/ERC165.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
import "../../utils/EnumerableSet.sol";
import "../../utils/EnumerableMap.sol";
import "../../utils/Strings.sol";
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
using SafeMath for uint256;
using Address for address;
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableMap for EnumerableMap.UintToAddressMap;
using Strings for uint256;
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
mapping (address => EnumerableSet.UintSet) private _holderTokens;
EnumerableMap.UintToAddressMap private _tokenOwners;
mapping (uint256 => address) private _tokenApprovals;
mapping (address => mapping (address => bool)) private _operatorApprovals;
string private _name;
string private _symbol;
mapping (uint256 => string) private _tokenURIs;
string private _baseURI;
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
constructor (string memory name_, string memory symbol_) public {
_name = name_;
_symbol = symbol_;
_registerInterface(_INTERFACE_ID_ERC721);
_registerInterface(_INTERFACE_ID_ERC721_METADATA);
_registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
}
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _holderTokens[owner].length();
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = baseURI();
if (bytes(base).length == 0) {
return _tokenURI;
}
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
return string(abi.encodePacked(base, tokenId.toString()));
}
function baseURI() public view virtual returns (string memory) {
return _baseURI;
}
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
return _holderTokens[owner].at(index);
}
function totalSupply() public view virtual override returns (uint256) {
return _tokenOwners.length();
}
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
(uint256 tokenId, ) = _tokenOwners.at(index);
return tokenId;
}
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved) public virtual override {
require(operator != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _tokenOwners.contains(tokenId);
}
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));
}
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
_mint(to, tokenId);
require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_holderTokens[to].add(tokenId);
_tokenOwners.set(tokenId, to);
emit Transfer(address(0), to, tokenId);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
_approve(address(0), tokenId);
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
_holderTokens[owner].remove(tokenId);
_tokenOwners.remove(tokenId);
emit Transfer(owner, address(0), tokenId);
}
function _transfer(address from, address to, uint256 tokenId) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
_approve(address(0), tokenId);
_holderTokens[from].remove(tokenId);
_holderTokens[to].add(tokenId);
_tokenOwners.set(tokenId, to);
emit Transfer(from, to, tokenId);
}
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
function _setBaseURI(string memory baseURI_) internal virtual {
_baseURI = baseURI_;
}
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
private returns (bool)
{
if (!to.isContract()) {
return true;
}
bytes memory returndata = to.functionCall(abi.encodeWithSelector(
IERC721Receiver(to).onERC721Received.selector,
_msgSender(),
from,
tokenId,
_data
), "ERC721: transfer to non ERC721Receiver implementer");
bytes4 retval = abi.decode(returndata, (bytes4));
return (retval == _ERC721_RECEIVED);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }
}
文件 9 的 58:EnumerableMap.sol
pragma solidity >=0.6.0 <0.8.0;
library EnumerableMap {
struct MapEntry {
bytes32 _key;
bytes32 _value;
}
struct Map {
MapEntry[] _entries;
mapping (bytes32 => uint256) _indexes;
}
function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {
uint256 keyIndex = map._indexes[key];
if (keyIndex == 0) {
map._entries.push(MapEntry({ _key: key, _value: value }));
map._indexes[key] = map._entries.length;
return true;
} else {
map._entries[keyIndex - 1]._value = value;
return false;
}
}
function _remove(Map storage map, bytes32 key) private returns (bool) {
uint256 keyIndex = map._indexes[key];
if (keyIndex != 0) {
uint256 toDeleteIndex = keyIndex - 1;
uint256 lastIndex = map._entries.length - 1;
MapEntry storage lastEntry = map._entries[lastIndex];
map._entries[toDeleteIndex] = lastEntry;
map._indexes[lastEntry._key] = toDeleteIndex + 1;
map._entries.pop();
delete map._indexes[key];
return true;
} else {
return false;
}
}
function _contains(Map storage map, bytes32 key) private view returns (bool) {
return map._indexes[key] != 0;
}
function _length(Map storage map) private view returns (uint256) {
return map._entries.length;
}
function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
require(map._entries.length > index, "EnumerableMap: index out of bounds");
MapEntry storage entry = map._entries[index];
return (entry._key, entry._value);
}
function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
uint256 keyIndex = map._indexes[key];
if (keyIndex == 0) return (false, 0);
return (true, map._entries[keyIndex - 1]._value);
}
function _get(Map storage map, bytes32 key) private view returns (bytes32) {
uint256 keyIndex = map._indexes[key];
require(keyIndex != 0, "EnumerableMap: nonexistent key");
return map._entries[keyIndex - 1]._value;
}
function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {
uint256 keyIndex = map._indexes[key];
require(keyIndex != 0, errorMessage);
return map._entries[keyIndex - 1]._value;
}
struct UintToAddressMap {
Map _inner;
}
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return _remove(map._inner, bytes32(key));
}
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return _contains(map._inner, bytes32(key));
}
function length(UintToAddressMap storage map) internal view returns (uint256) {
return _length(map._inner);
}
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = _at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
(bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(value))));
}
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, bytes32(key)))));
}
function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));
}
}
文件 10 的 58:EnumerableSet.sol
pragma solidity >=0.6.0 <0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping (bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
bytes32 lastvalue = set._values[lastIndex];
set._values[toDeleteIndex] = lastvalue;
set._indexes[lastvalue] = toDeleteIndex + 1;
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
return set._values[index];
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}
文件 11 的 58:FakePriceProvider.sol
pragma solidity 0.6.12;
import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
contract FakePriceProvider is AggregatorV3Interface {
uint256 public price;
uint8 public override decimals = 8;
string public override description = "Test implementation";
uint256 public override version = 0;
constructor(uint256 _price) public {
price = _price;
}
function setPrice(uint256 _price) external {
price = _price;
}
function getRoundData(uint80) external override view returns (uint80, int256, uint256, uint256, uint80) {
revert("Test implementation");
}
function latestAnswer() external view returns(int result) {
(, result, , , ) = latestRoundData();
}
function latestRoundData()
public
override
view
returns (
uint80,
int256 answer,
uint256,
uint256,
uint80
)
{
answer = int(price);
}
}
文件 12 的 58:Governable.sol
pragma solidity 0.6.12;
import "../Interfaces/Keep3r/IGovernable.sol";
abstract contract Governable is IGovernable {
address public governor;
address public pendingGovernor;
constructor(address _governor) public {
require(_governor != address(0), "governable::governor-should-not-be-zero-address");
governor = _governor;
}
function _setPendingGovernor(address _pendingGovernor) internal {
require(_pendingGovernor != address(0), "governable::pending-governor-should-not-be-zero-address");
pendingGovernor = _pendingGovernor;
emit PendingGovernorSet(_pendingGovernor);
}
function _acceptGovernor() internal {
governor = pendingGovernor;
pendingGovernor = address(0);
emit GovernorAccepted();
}
modifier onlyGovernor {
require(msg.sender == governor, "governable::only-governor");
_;
}
modifier onlyPendingGovernor {
require(msg.sender == pendingGovernor, "governable::only-pending-governor");
_;
}
}
文件 13 的 58:IChainLinkFeed.sol
pragma solidity 0.6.12;
interface IChainLinkFeed {
function latestAnswer() external view returns (int256);
}
文件 14 的 58:ICollectableDust.sol
pragma solidity >=0.6.12;
interface ICollectableDust {
event DustSent(address _to, address token, uint256 amount);
function sendDust(
address _to,
address _token,
uint256 _amount
) external;
}
文件 15 的 58:IERC165.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 16 的 58:IERC20.sol
pragma solidity >=0.5.0;
interface IERC20Uniswap {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
}
文件 17 的 58:IERC721.sol
pragma solidity >=0.6.2 <0.8.0;
import "../../introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}
文件 18 的 58:IERC721Enumerable.sol
pragma solidity >=0.6.2 <0.8.0;
import "./IERC721.sol";
interface IERC721Enumerable is IERC721 {
function totalSupply() external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
function tokenByIndex(uint256 index) external view returns (uint256);
}
文件 19 的 58:IERC721Metadata.sol
pragma solidity >=0.6.2 <0.8.0;
import "./IERC721.sol";
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 20 的 58:IERC721Receiver.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC721Receiver {
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}
文件 21 的 58:IGovernable.sol
pragma solidity >=0.6.12;
interface IGovernable {
event PendingGovernorSet(address pendingGovernor);
event GovernorAccepted();
function setPendingGovernor(address _pendingGovernor) external;
function acceptGovernor() external;
}
文件 22 的 58:IKeep3rV1.sol
pragma solidity >=0.6.12;
interface IKeep3rV1 {
function KPRH() external returns (address);
function name() external returns (string memory);
function isKeeper(address) external returns (bool);
function worked(address keeper) external;
function workReceipt(address keeper, uint amount) external;
function receiptETH(address keeper, uint256 amount) external;
function receipt(address credit, address keeper, uint256 amount) external;
function addKPRCredit(address job, uint256 amount) external;
function addCredit(address asset, address job, uint256 amount) external;
function addJob(address job) external;
}
文件 23 的 58:IKeep3rV1Helper.sol
pragma solidity >=0.6.12;
interface IKeep3rV1Helper {
function quote(uint256) external view returns (uint256);
}
文件 24 的 58:IToken.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IToken is IERC20{
function decimals() external view returns (uint);
}
文件 25 的 58:IUniswapV2Callee.sol
pragma solidity >=0.5.0;
interface IUniswapV2Callee {
function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external;
}
文件 26 的 58:IUniswapV2Factory.sol
pragma solidity >=0.5.0;
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function migrator() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
function setMigrator(address) external;
}
文件 27 的 58:IUniswapV2Pair.sol
pragma solidity >=0.5.0;
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
文件 28 的 58:IUniswapV2Router01.sol
pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
文件 29 的 58:IUniswapV2Router02.sol
pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
文件 30 的 58:IWETH.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWETH is IERC20 {
function deposit() payable external;
function withdraw(uint wad) external;
}
文件 31 的 58:IWHAsset.sol
pragma solidity 0.6.12;
interface IWHAssetv2 {
event Wrap(address indexed account, uint32 indexed tokenId, uint88 cost, uint88 amount, uint48 strike, uint32 expiration);
event Unwrap(address indexed account, uint32 indexed tokenId, uint128 closePrice, uint128 optionProfit);
struct Underlying {
bool active;
address owner;
uint88 amount;
uint48 expiration;
uint48 strike;
}
function wrap(uint128 amount, uint period, address to, bool mintToken, uint minUSDCPremium) payable external returns (uint newTokenId);
function unwrap(uint tokenId) external;
function autoUnwrap(uint tokenId, address rewardRecipient) external returns (uint);
function autoUnwrapAll(uint[] calldata tokenIds, address rewardRecipient) external returns (uint);
function wrapAfterSwap(uint total, uint protectionPeriod, address to, bool mintToken, uint minUSDCPremium) external returns (uint newTokenId);
}
文件 32 的 58:IWHSwapRouter.sol
pragma solidity 0.6.12;
interface IWHSwapRouter {
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactTokensForTokensAndWrap(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline,
uint protectionPeriod,
bool mintToken,
uint minUSDCPremium
) external returns (uint[] memory amounts, uint newTokenId);
function swapTokensForExactTokensAndWrap(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline,
uint protectionPeriod,
bool mintToken,
uint minUSDCPremium
) external returns (uint[] memory amounts, uint newTokenId);
function swapExactETHForTokensAndWrap(uint amountOutMin, address[] calldata path, address to, uint deadline, uint protectionPeriod, bool mintToken, uint minUSDCPremium)
external
payable
returns (uint[] memory amounts, uint newTokenId);
function swapETHForExactTokensAndWrap(uint amountOut, address[] calldata path, address to, uint deadline, uint protectionPeriod, bool mintToken, uint minUSDCPremium)
external
payable
returns (uint[] memory amounts, uint newTokenId);
function swapExactTokensForETHAndWrap(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline, uint protectionPeriod, bool mintToken, uint minUSDCPremium)
external
returns(uint[] memory amounts, uint newTokenId);
function swapTokensForExactETHAndWrap(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline, uint protectionPeriod, bool mintToken, uint minUSDCPremium)
external
returns (uint[] memory amounts, uint newTokenId);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut)
external
pure
returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut)
external
pure
returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] memory path)
external
view
returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] memory path)
external
view
returns (uint[] memory amounts);
}
文件 33 的 58:IWhiteOptionsPricer.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
interface IWhiteOptionsPricer {
function getOptionPrice(
uint256 period,
uint256 amount,
uint256 strike
)
external
view
returns (uint256 total);
function getAmountToWrapFromTotal(uint total, uint period) external view returns (uint);
}
文件 34 的 58:IWhiteStakingERC20.sol
pragma solidity 0.6.12;
interface IWhiteStaking {
event Claim(address indexed acount, uint amount);
event Profit(uint amount);
function claimProfit() external returns (uint profit);
function deposit(uint amount) external;
function withdraw(uint amount) external;
function profitOf(address account) external view returns (uint);
}
interface IWhiteStakingERC20 {
function sendProfit(uint amount) external;
}
文件 35 的 58:IWhiteUSDCPool.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
interface ILiquidityPool {
struct LockedLiquidity { uint120 amount; uint120 premium; bool locked; }
event Profit(uint indexed id, uint amount);
event Loss(uint indexed id, uint amount);
event Provide(address indexed account, uint256 amount, uint256 writeAmount);
event Withdraw(address indexed account, uint256 amount, uint256 writeAmount);
function unlock(uint256 id) external;
function setLockupPeriod(uint value) external;
function deleteLockedLiquidity(uint id) external;
function totalBalance() external view returns (uint256 amount);
function setAllowedWHAsset(address _whAsset, bool approved) external;
function send(uint256 id, address payable account, uint256 amount, uint payKeep3r) external;
}
interface IWhiteUSDCPool is ILiquidityPool {
function lock(uint id, uint256 amountToLock, uint256 premium) external;
function token() external view returns (IERC20);
function payKeep3r(address keep3r) external returns (uint amount);
}
文件 36 的 58:Math.sol
pragma solidity =0.6.12;
library Math {
function min(uint x, uint y) internal pure returns (uint z) {
z = x < y ? x : y;
}
function sqrt(uint y) internal pure returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
文件 37 的 58:MockTokens.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
contract FakeWBTC is ERC20("FakeWBTC", "FAKE") {
constructor() public {
_setupDecimals(8);
}
function mintTo(address account, uint256 amount) public {
_mint(account, amount);
}
function mint(uint256 amount) public {
_mint(msg.sender, amount);
}
}
contract FakeWHITE is ERC20("FakeWHITE", "FAKEWHITE") {
function mintTo(address account, uint256 amount) public {
_mint(account, amount);
}
function mint(uint256 amount) public {
_mint(msg.sender, amount);
}
}
contract FakeWETH is ERC20("FakeWETH", "FAKETH") {
receive() external payable {}
function mintTo(address account, uint256 amount) public {
_mint(account, amount);
}
function mint(uint256 amount) public {
_mint(msg.sender, amount);
}
function deposit() external payable {
_mint(msg.sender, msg.value);
}
function withdraw(uint wad) external {
payable(msg.sender).transfer(wad);
_burn(msg.sender, wad);
}
}
contract FakeUSDC is ERC20("FakeUSDC", "FAKEU") {
using SafeERC20 for ERC20;
constructor() public {
_setupDecimals(6);
}
function mintTo(address account, uint256 amount) public {
_mint(account, amount);
}
function mint(uint256 amount) public {
_mint(msg.sender, amount);
}
}
文件 38 的 58:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 39 的 58:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
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 safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 40 的 58:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 41 的 58:Strings.sol
pragma solidity >=0.6.0 <0.8.0;
library Strings {
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
uint256 index = digits - 1;
temp = value;
while (temp != 0) {
buffer[index--] = bytes1(uint8(48 + temp % 10));
temp /= 10;
}
return string(buffer);
}
}
文件 42 的 58:SushiSwapFactoryMock.sol
pragma solidity 0.6.12;
import "@sushiswap/core/contracts/uniswapv2/interfaces/IUniswapV2Factory.sol";
import "@sushiswap/core/contracts/uniswapv2/UniswapV2Factory.sol";
contract SushiSwapFactoryMock is UniswapV2Factory {
constructor() public UniswapV2Factory(msg.sender) {
return;
}
}
文件 43 的 58:SushiSwapPairMock.sol
pragma solidity 0.6.12;
import "@sushiswap/core/contracts/uniswapv2/UniswapV2Pair.sol";
contract SushiSwapPairMock is UniswapV2Pair {
constructor() public UniswapV2Pair() {
return;
}
}
文件 44 的 58:TransferHelper.sol
pragma solidity >=0.6.0;
library TransferHelper {
function safeApprove(address token, address to, uint value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(address token, address to, uint value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint value) internal {
(bool success,) = to.call{value:value}(new bytes(0));
require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}
}
文件 45 的 58:UQ112x112.sol
pragma solidity =0.6.12;
library UQ112x112 {
uint224 constant Q112 = 2**112;
function encode(uint112 y) internal pure returns (uint224 z) {
z = uint224(y) * Q112;
}
function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
z = x / uint224(y);
}
}
文件 46 的 58:UniswapV2ERC20.sol
pragma solidity =0.6.12;
import './libraries/SafeMath.sol';
contract UniswapV2ERC20 {
using SafeMathUniswap for uint;
string public constant name = 'SushiSwap LP Token';
string public constant symbol = 'SLP';
uint8 public constant decimals = 18;
uint public totalSupply;
mapping(address => uint) public balanceOf;
mapping(address => mapping(address => uint)) public allowance;
bytes32 public DOMAIN_SEPARATOR;
bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address => uint) public nonces;
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
constructor() public {
uint chainId;
assembly {
chainId := chainid()
}
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
keccak256(bytes(name)),
keccak256(bytes('1')),
chainId,
address(this)
)
);
}
function _mint(address to, uint value) internal {
totalSupply = totalSupply.add(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(address(0), to, value);
}
function _burn(address from, uint value) internal {
balanceOf[from] = balanceOf[from].sub(value);
totalSupply = totalSupply.sub(value);
emit Transfer(from, address(0), value);
}
function _approve(address owner, address spender, uint value) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _transfer(address from, address to, uint value) private {
balanceOf[from] = balanceOf[from].sub(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(from, to, value);
}
function approve(address spender, uint value) external returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transfer(address to, uint value) external returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function transferFrom(address from, address to, uint value) external returns (bool) {
if (allowance[from][msg.sender] != uint(-1)) {
allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
}
_transfer(from, to, value);
return true;
}
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
require(deadline >= block.timestamp, 'UniswapV2: EXPIRED');
bytes32 digest = keccak256(
abi.encodePacked(
'\x19\x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE');
_approve(owner, spender, value);
}
}
文件 47 的 58:UniswapV2Factory.sol
pragma solidity =0.6.12;
import './interfaces/IUniswapV2Factory.sol';
import './UniswapV2Pair.sol';
contract UniswapV2Factory is IUniswapV2Factory {
address public override feeTo;
address public override feeToSetter;
address public override migrator;
mapping(address => mapping(address => address)) public override getPair;
address[] public override allPairs;
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
constructor(address _feeToSetter) public {
feeToSetter = _feeToSetter;
}
function allPairsLength() external override view returns (uint) {
return allPairs.length;
}
function pairCodeHash() external pure returns (bytes32) {
return keccak256(type(UniswapV2Pair).creationCode);
}
function createPair(address tokenA, address tokenB) external override returns (address pair) {
require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');
(address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS');
require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS');
bytes memory bytecode = type(UniswapV2Pair).creationCode;
bytes32 salt = keccak256(abi.encodePacked(token0, token1));
assembly {
pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
}
UniswapV2Pair(pair).initialize(token0, token1);
getPair[token0][token1] = pair;
getPair[token1][token0] = pair;
allPairs.push(pair);
emit PairCreated(token0, token1, pair, allPairs.length);
}
function setFeeTo(address _feeTo) external override {
require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
feeTo = _feeTo;
}
function setMigrator(address _migrator) external override {
require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
migrator = _migrator;
}
function setFeeToSetter(address _feeToSetter) external override {
require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
feeToSetter = _feeToSetter;
}
}
文件 48 的 58:UniswapV2Library.sol
pragma solidity >=0.5.0;
import '../interfaces/IUniswapV2Pair.sol';
import "./SafeMath.sol";
library UniswapV2Library {
using SafeMathUniswap for uint;
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES');
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS');
}
function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {
(address token0, address token1) = sortTokens(tokenA, tokenB);
pair = address(uint(keccak256(abi.encodePacked(
hex'ff',
factory,
keccak256(abi.encodePacked(token0, token1)),
hex'fa418eb2c6e15c39605695377d0e364aca1c3c56b333eefe9c0d4b707662f785'
))));
}
function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {
(address token0,) = sortTokens(tokenA, tokenB);
(uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).getReserves();
(reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
}
function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) {
require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT');
require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
amountB = amountA.mul(reserveB) / reserveA;
}
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
uint amountInWithFee = amountIn.mul(997);
uint numerator = amountInWithFee.mul(reserveOut);
uint denominator = reserveIn.mul(1000).add(amountInWithFee);
amountOut = numerator / denominator;
}
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) {
require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT');
require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
uint numerator = reserveIn.mul(amountOut).mul(1000);
uint denominator = reserveOut.sub(amountOut).mul(997);
amountIn = (numerator / denominator).add(1);
}
function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) {
require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
amounts = new uint[](path.length);
amounts[0] = amountIn;
for (uint i; i < path.length - 1; i++) {
(uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]);
amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
}
}
function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) {
require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
amounts = new uint[](path.length);
amounts[amounts.length - 1] = amountOut;
for (uint i = path.length - 1; i > 0; i--) {
(uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]);
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
}
}
}
文件 49 的 58:UniswapV2Pair.sol
pragma solidity =0.6.12;
import './UniswapV2ERC20.sol';
import './libraries/Math.sol';
import './libraries/UQ112x112.sol';
import './interfaces/IERC20.sol';
import './interfaces/IUniswapV2Factory.sol';
import './interfaces/IUniswapV2Callee.sol';
interface IMigrator {
function desiredLiquidity() external view returns (uint256);
}
contract UniswapV2Pair is UniswapV2ERC20 {
using SafeMathUniswap for uint;
using UQ112x112 for uint224;
uint public constant MINIMUM_LIQUIDITY = 10**3;
bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
address public factory;
address public token0;
address public token1;
uint112 private reserve0;
uint112 private reserve1;
uint32 private blockTimestampLast;
uint public price0CumulativeLast;
uint public price1CumulativeLast;
uint public kLast;
uint private unlocked = 1;
modifier lock() {
require(unlocked == 1, 'UniswapV2: LOCKED');
unlocked = 0;
_;
unlocked = 1;
}
function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
_reserve0 = reserve0;
_reserve1 = reserve1;
_blockTimestampLast = blockTimestampLast;
}
function _safeTransfer(address token, address to, uint value) private {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED');
}
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
constructor() public {
factory = msg.sender;
}
function initialize(address _token0, address _token1) external {
require(msg.sender == factory, 'UniswapV2: FORBIDDEN');
token0 = _token0;
token1 = _token1;
}
function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW');
uint32 blockTimestamp = uint32(block.timestamp % 2**32);
uint32 timeElapsed = blockTimestamp - blockTimestampLast;
if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
}
reserve0 = uint112(balance0);
reserve1 = uint112(balance1);
blockTimestampLast = blockTimestamp;
emit Sync(reserve0, reserve1);
}
function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) {
address feeTo = IUniswapV2Factory(factory).feeTo();
feeOn = feeTo != address(0);
uint _kLast = kLast;
if (feeOn) {
if (_kLast != 0) {
uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1));
uint rootKLast = Math.sqrt(_kLast);
if (rootK > rootKLast) {
uint numerator = totalSupply.mul(rootK.sub(rootKLast));
uint denominator = rootK.mul(5).add(rootKLast);
uint liquidity = numerator / denominator;
if (liquidity > 0) _mint(feeTo, liquidity);
}
}
} else if (_kLast != 0) {
kLast = 0;
}
}
function mint(address to) external lock returns (uint liquidity) {
(uint112 _reserve0, uint112 _reserve1,) = getReserves();
uint balance0 = IERC20Uniswap(token0).balanceOf(address(this));
uint balance1 = IERC20Uniswap(token1).balanceOf(address(this));
uint amount0 = balance0.sub(_reserve0);
uint amount1 = balance1.sub(_reserve1);
bool feeOn = _mintFee(_reserve0, _reserve1);
uint _totalSupply = totalSupply;
if (_totalSupply == 0) {
address migrator = IUniswapV2Factory(factory).migrator();
if (msg.sender == migrator) {
liquidity = IMigrator(migrator).desiredLiquidity();
require(liquidity > 0 && liquidity != uint256(-1), "Bad desired liquidity");
} else {
require(migrator == address(0), "Must not have migrator");
liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
_mint(address(0), MINIMUM_LIQUIDITY);
}
} else {
liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1);
}
require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED');
_mint(to, liquidity);
_update(balance0, balance1, _reserve0, _reserve1);
if (feeOn) kLast = uint(reserve0).mul(reserve1);
emit Mint(msg.sender, amount0, amount1);
}
function burn(address to) external lock returns (uint amount0, uint amount1) {
(uint112 _reserve0, uint112 _reserve1,) = getReserves();
address _token0 = token0;
address _token1 = token1;
uint balance0 = IERC20Uniswap(_token0).balanceOf(address(this));
uint balance1 = IERC20Uniswap(_token1).balanceOf(address(this));
uint liquidity = balanceOf[address(this)];
bool feeOn = _mintFee(_reserve0, _reserve1);
uint _totalSupply = totalSupply;
amount0 = liquidity.mul(balance0) / _totalSupply;
amount1 = liquidity.mul(balance1) / _totalSupply;
require(amount0 > 0 && amount1 > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED');
_burn(address(this), liquidity);
_safeTransfer(_token0, to, amount0);
_safeTransfer(_token1, to, amount1);
balance0 = IERC20Uniswap(_token0).balanceOf(address(this));
balance1 = IERC20Uniswap(_token1).balanceOf(address(this));
_update(balance0, balance1, _reserve0, _reserve1);
if (feeOn) kLast = uint(reserve0).mul(reserve1);
emit Burn(msg.sender, amount0, amount1, to);
}
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT');
(uint112 _reserve0, uint112 _reserve1,) = getReserves();
require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY');
uint balance0;
uint balance1;
{
address _token0 = token0;
address _token1 = token1;
require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO');
if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out);
if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out);
if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);
balance0 = IERC20Uniswap(_token0).balanceOf(address(this));
balance1 = IERC20Uniswap(_token1).balanceOf(address(this));
}
uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT');
{
uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));
require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K');
}
_update(balance0, balance1, _reserve0, _reserve1);
emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
}
function skim(address to) external lock {
address _token0 = token0;
address _token1 = token1;
_safeTransfer(_token0, to, IERC20Uniswap(_token0).balanceOf(address(this)).sub(reserve0));
_safeTransfer(_token1, to, IERC20Uniswap(_token1).balanceOf(address(this)).sub(reserve1));
}
function sync() external lock {
_update(IERC20Uniswap(token0).balanceOf(address(this)), IERC20Uniswap(token1).balanceOf(address(this)), reserve0, reserve1);
}
}
文件 50 的 58:WHAssetv2.sol
pragma solidity 0.6.12;
import "./Interfaces/IWETH.sol";
import "./Interfaces/IToken.sol";
import "./Interfaces/IWHAsset.sol";
import "./Interfaces/IWhiteUSDCPool.sol";
import "./Interfaces/IWhiteOptionsPricer.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol";
interface IKeep3r {
function getRequestedPayment() external view returns (uint);
}
abstract contract WHAssetv2 is ERC721, IWHAssetv2, Ownable {
using Counters for Counters.Counter;
using SafeMath for uint;
using SafeMath for uint48;
uint256 internal constant PRICE_DECIMALS = 1e8;
uint256 public optionCollateralizationRatio = 100;
address[] public underlyingToStableSwapPath;
Counters.Counter private _tokenIds;
IWhiteUSDCPool public immutable pool;
IWhiteOptionsPricer public whiteOptionsPricer;
IUniswapV2Router02 public swapRouter;
AggregatorV3Interface public immutable priceProvider;
address public keep3r;
uint internal immutable DECIMALS;
IERC20 public immutable stablecoin;
mapping(address => bool) public routers;
mapping(uint => Underlying) public underlying;
mapping(address => bool) public autoUnwrapDisabled;
constructor(
IUniswapV2Router02 _swapRouter,
IToken _stablecoin,
IToken _token,
AggregatorV3Interface _priceProvider,
IWhiteUSDCPool _pool,
IWhiteOptionsPricer _whiteOptionsPricer,
string memory _name,
string memory _symbol) public ERC721(_name, _symbol)
{
uint _DECIMALS = 10 ** (uint(IToken(_token).decimals()).sub(uint(IToken(_stablecoin).decimals()))) * PRICE_DECIMALS;
DECIMALS = _DECIMALS;
address[] memory _underlyingToStableSwapPath = new address[](2);
_underlyingToStableSwapPath[0] = address(_token);
_underlyingToStableSwapPath[1] = address(_stablecoin);
underlyingToStableSwapPath = _underlyingToStableSwapPath;
setSwapRouter(_swapRouter);
whiteOptionsPricer = _whiteOptionsPricer;
priceProvider = _priceProvider;
stablecoin = _stablecoin;
pool = _pool;
}
modifier onlyTokenOwner(uint tokenId) {
require(underlying[tokenId].owner == msg.sender, "msg.sender != owner");
_;
}
modifier onlyRouter {
require(routers[msg.sender], "!not allowed");
_;
}
function setSwapRouter(IUniswapV2Router02 newRouter) public onlyOwner {
swapRouter = newRouter;
setRouter(address(newRouter), true);
}
function setRouter(address _router, bool allowed) public onlyOwner {
routers[_router] = allowed;
}
function setKeep3r(address newKeep3r) external onlyOwner {
keep3r = newKeep3r;
}
function wrapCost(uint amount, uint period) view external returns (uint cost){
uint strike = _currentPrice();
return whiteOptionsPricer.getOptionPrice(period, amount, strike);
}
function wrap(uint128 amount, uint period, address to, bool _mintToken, uint minPremiumUSDC) payable public override virtual returns (uint newTokenId) {
newTokenId = _wrap(uint(amount), period, to, true, _mintToken, minPremiumUSDC);
}
function mintToken(uint tokenId) external {
require(underlying[tokenId].active && underlying[tokenId].owner == msg.sender, "!not-tokenizable");
_mint(msg.sender, tokenId);
}
function unwrap(uint tokenId) external override onlyTokenOwner(tokenId) {
_unwrap(tokenId);
}
function listAutoUnwrapable() external view returns (uint[] memory list) {
uint counter = 0;
for(uint i = 0; i <= _tokenIds.current() ; i++) {
if(isAutoUnwrapable(i)) counter++;
}
list = new uint[](counter);
uint index = 0;
for(uint i = 0; i <= _tokenIds.current() ; i++) {
if(isAutoUnwrapable(i)){
list[index] = i;
index++;
}
if(index>=counter) return list;
}
}
function autoUnwrapAll(uint[] calldata list, address rewardRecipient) external override returns (uint reward) {
for(uint i = 0; i < list.length; i++){
if(isAutoUnwrapable(list[i])) {
_unwrap(list[i]);
}
}
if(address(msg.sender).isContract() && msg.sender == keep3r) reward = pool.payKeep3r(rewardRecipient);
}
function autoUnwrap(uint tokenId, address rewardRecipient) public override returns (uint reward) {
require(isAutoUnwrapable(tokenId), "!not-unwrapable");
_unwrap(tokenId);
if(address(msg.sender).isContract() && msg.sender == keep3r) reward = pool.payKeep3r(rewardRecipient);
}
function setAutoUnwrapDisabled(bool disabled) external {
autoUnwrapDisabled[msg.sender] = disabled;
}
function isAutoUnwrapable(uint tokenId) public view returns (bool) {
Underlying memory _underlying = underlying[tokenId];
if(autoUnwrapDisabled[_underlying.owner]) return false;
if(!_underlying.active) return false;
bool ITM = false;
uint currentPrice = _currentPrice();
ITM = currentPrice < _underlying.strike;
if (ITM && ((_underlying.expiration.sub(30 minutes) <= block.timestamp) && (_underlying.expiration >= block.timestamp))) {
return true;
}
return false;
}
function _wrap(uint amount, uint period, address to, bool receiveAsset, bool _mintToken, uint minPremiumUSDC) internal returns (uint newTokenId){
_tokenIds.increment();
newTokenId = _tokenIds.current();
uint strike = _currentPrice();
uint total = whiteOptionsPricer.getOptionPrice(period, amount, strike);
if(receiveAsset) _receiveAsset(msg.sender, amount, total);
_createHedge(newTokenId, total, period, amount, strike, to, minPremiumUSDC);
if(_mintToken) _mint(to, newTokenId);
emit Wrap(to, uint32(newTokenId), uint88(total), uint88(amount), uint48(strike), uint32(block.timestamp+period));
}
function _createHedge(uint tokenId, uint totalFee, uint period, uint amount, uint strike, address owner, uint minPremiumUSDC) internal {
uint collateral = amount.mul(strike).mul(optionCollateralizationRatio).div(100).div(DECIMALS);
underlying[tokenId] = Underlying(
bool(true),
address(owner),
uint88(amount),
uint48(block.timestamp + period),
uint48(strike)
);
uint[] memory amounts = swapRouter.swapExactTokensForTokens(
totalFee,
minPremiumUSDC,
underlyingToStableSwapPath,
address(pool),
block.timestamp
);
uint totalStablecoin = amounts[amounts.length - 1];
pool.lock(tokenId, collateral, totalStablecoin);
}
function _exercise(uint tokenId, address owner) internal returns (uint optionProfit, uint amount, uint underlyingCurrentPrice) {
Underlying storage _underlying = underlying[tokenId];
amount = _underlying.amount;
underlyingCurrentPrice = _currentPrice();
if(_underlying.expiration < block.timestamp){
pool.unlock(tokenId);
optionProfit = 0;
} else {
(optionProfit) = _payProfit(owner, tokenId, _underlying.strike, _underlying.amount, underlyingCurrentPrice);
}
}
function _payProfit(address owner, uint tokenId, uint strike, uint amount, uint underlyingCurrentPrice)
internal
returns (uint profit)
{
if(strike <= underlyingCurrentPrice){
profit = 0;
} else {
profit = strike.sub(underlyingCurrentPrice).mul(amount).div(DECIMALS);
}
address _keep3r = address(msg.sender).isContract() ? keep3r : address(0);
uint payKeep3r = _keep3r != address(0) ? IKeep3r(_keep3r).getRequestedPayment() : 0;
require(payKeep3r <= profit, "!keep3r-requested-too-much");
pool.send(tokenId, payable(owner), profit, payKeep3r);
}
function _unwrap(uint tokenId) internal returns (address owner, uint optionProfit) {
Underlying storage _underlying = underlying[tokenId];
owner = _underlying.owner;
require(owner != address(0), "!tokenId-does-not-exist");
require(_underlying.active, "!tokenId-does-not-exist");
(uint profit, uint amount, uint underlyingCurrentPrice) = _exercise(tokenId, owner);
if(_exists(tokenId)) _burn(tokenId);
_underlying.active = false;
_sendTotal(payable(owner), amount);
optionProfit = profit;
emit Unwrap(owner, uint32(tokenId), uint128(underlyingCurrentPrice), uint128(profit));
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override {
if(from != address(0) && to != address(0)){
require(underlying[tokenId].owner == from, "!sth-went-wrong");
underlying[tokenId].owner = to;
}
}
function _receiveAsset(address from, uint amount, uint hedgeCost) internal virtual;
function _sendTotal(address payable from, uint amount) internal virtual;
function _currentPrice() internal view returns (uint) {
(
,
int price,
,
,
) = priceProvider.latestRoundData();
return uint(price);
}
}
文件 51 的 58:WHERC20v2.sol
pragma solidity 0.6.12;
import "../WHAssetv2.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
contract WHERC20v2 is WHAssetv2 {
using SafeERC20 for IERC20;
using SafeMath for uint;
IERC20 public immutable token;
constructor(
IUniswapV2Router02 _swapRouter,
IToken _stablecoin,
IToken _token,
AggregatorV3Interface _priceProvider,
IWhiteUSDCPool _pool,
IWhiteOptionsPricer _whiteOptionsPricer,
string memory _name,
string memory _symbol
) public WHAssetv2(_swapRouter, _stablecoin, _token, _priceProvider, _pool, _whiteOptionsPricer, _name, _symbol) {
token = _token;
IERC20(_stablecoin).safeApprove(address(_pool), type(uint256).max);
IERC20(_token).safeApprove(address(_swapRouter), type(uint256).max);
}
function wrap(uint128 amount, uint period, address to, bool _mintToken, uint minPremiumUSDC) payable public override returns (uint newTokenId) {
require(msg.value == 0, "!eth not accepted");
newTokenId = super.wrap(amount, period, to, _mintToken, minPremiumUSDC);
}
function wrapAfterSwap(uint total, uint protectionPeriod, address to, bool mintToken, uint minUSDCPremium) external onlyRouter override returns (uint newTokenId) {
uint amountToWrap = whiteOptionsPricer.getAmountToWrapFromTotal(total, protectionPeriod);
newTokenId = _wrap(amountToWrap, protectionPeriod, to, false, mintToken, minUSDCPremium);
}
function _receiveAsset(address from, uint amount, uint toUsdc) internal override {
token.safeTransferFrom(from, address(this), amount.add(toUsdc));
}
function _sendTotal(address payable to, uint amount) internal override {
token.safeTransfer(to, amount);
}
}
文件 52 的 58:WHETHv2.sol
pragma solidity 0.6.12;
import "../WHAssetv2.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
contract WHETHv2 is WHAssetv2 {
using SafeERC20 for IERC20;
using SafeMath for uint;
address public WETH;
constructor(
IUniswapV2Router02 _swapRouter,
IToken _stablecoin,
AggregatorV3Interface _priceProvider,
IWhiteUSDCPool _pool,
IWhiteOptionsPricer _whiteOptionsPricer
) public WHAssetv2(_swapRouter, _stablecoin, IToken(_swapRouter.WETH()), _priceProvider, _pool, _whiteOptionsPricer, "Whiteheart Hedged ETH", "WHETH") {
connectRouter(_swapRouter);
IERC20(_stablecoin).safeApprove(address(_pool), type(uint256).max);
}
receive() payable external {}
function connectRouter(IUniswapV2Router02 _swapRouter) public onlyOwner {
WETH = _swapRouter.WETH();
IERC20(WETH).safeApprove(address(_swapRouter), type(uint256).max);
}
function wrapAfterSwap(uint total, uint protectionPeriod, address to, bool mintToken, uint minUSDCPremium) external onlyRouter override returns (uint newTokenId) {
uint amountToWrap = whiteOptionsPricer.getAmountToWrapFromTotal(total, protectionPeriod);
newTokenId = _wrap(amountToWrap, protectionPeriod, to, false, mintToken, minUSDCPremium);
}
function _receiveAsset(address from, uint amount, uint toUsdc) internal override {
uint received = msg.value;
require(received >= amount.add(toUsdc), "!wrong value");
if(received > amount.add(toUsdc)) payable(from).transfer(received.sub(amount.add(toUsdc)));
IWETH(WETH).deposit{value:amount.add(toUsdc)}();
}
function _sendTotal(address payable to, uint amount) internal override {
IWETH(WETH).withdraw(amount);
to.transfer(amount);
}
}
文件 53 的 58:WHSwapRouter.sol
pragma solidity 0.6.12;
import "./Interfaces/IWETH.sol";
import "./Interfaces/IWHAsset.sol";
import "./Interfaces/IWHSwapRouter.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@sushiswap/core/contracts/uniswapv2/libraries/TransferHelper.sol";
import "@sushiswap/core/contracts/uniswapv2/libraries/UniswapV2Library.sol";
contract WHSwapRouter is IWHSwapRouter, Ownable {
address public immutable factory;
address public immutable WETH;
mapping(address => address) public whAssets;
constructor(address _factory, address _WETH) public {
factory = _factory;
WETH = _WETH;
}
function setWHAsset(address token, address whAsset) external onlyOwner {
whAssets[token] = whAsset;
}
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external virtual override ensure(deadline) returns (uint[] memory amounts) {
amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'insufficient_output_amount');
TransferHelper.safeTransferFrom(
path[0], msg.sender, UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0]
);
_swap(amounts, path, to);
}
function swapExactTokensForTokensAndWrap(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline,
uint protectionPeriod,
bool mintToken,
uint minUSDCPremium
) external virtual override ensure(deadline) returns (uint[] memory amounts, uint newTokenId){
amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, 'insufficient_output_amount');
{
address[] calldata _path = path;
TransferHelper.safeTransferFrom(
_path[0], msg.sender, UniswapV2Library.pairFor(factory, _path[0], _path[1]), amounts[0]
);
}
newTokenId = _swapAndWrap(path, amounts, protectionPeriod, to, mintToken, minUSDCPremium);
}
function swapTokensForExactTokensAndWrap(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline,
uint protectionPeriod,
bool mintToken,
uint minUSDCPremium
) external virtual override ensure(deadline) returns (uint[] memory amounts, uint newTokenId) {
amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, 'excessive_input_amount');
{
address[] calldata _path = path;
TransferHelper.safeTransferFrom(
_path[0], msg.sender, UniswapV2Library.pairFor(factory, _path[0], _path[1]), amounts[0]
);
}
newTokenId = _swapAndWrap(path, amounts, protectionPeriod, to, mintToken, minUSDCPremium);
}
function swapExactETHForTokensAndWrap(uint amountOutMin, address[] calldata path, address to, uint deadline, uint protectionPeriod,
bool mintToken, uint minUSDCPremium)
external
virtual
payable
override
ensure(deadline)
returns (uint[] memory amounts, uint newTokenId)
{
address[] memory _path = path;
amounts = UniswapV2Library.getAmountsOut(factory, msg.value, _path);
require(amounts[amounts.length - 1] >= amountOutMin, 'insufficient_input_amount');
IWETH(WETH).deposit{value: amounts[0]}();
assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory, _path[0], _path[1]), amounts[0]));
newTokenId = _swapAndWrap(path, amounts, protectionPeriod, to, mintToken, minUSDCPremium);
}
function swapETHForExactTokensAndWrap(uint amountOut,
address[] calldata path,
address to,
uint deadline,
uint protectionPeriod,
bool mintToken,
uint minUSDCPremium
)
external
virtual
payable
override
ensure(deadline)
returns (uint[] memory amounts, uint newTokenId)
{
address[] memory _path = path;
require(_path[0] == WETH, 'invalid_path');
amounts = UniswapV2Library.getAmountsIn(factory, amountOut, _path);
require(amounts[0] <= msg.value, 'excessive_input_amount');
IWETH(WETH).deposit{value: amounts[0]}();
{
assert(IWETH(WETH).transfer(UniswapV2Library.pairFor(factory, _path[0], _path[1]), amounts[0]));
}
if(msg.value > amounts[0]) TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]);
newTokenId = _swapAndWrap(path, amounts, protectionPeriod, to, mintToken, minUSDCPremium);
}
function swapExactTokensForETHAndWrap(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline, uint protectionPeriod,
bool mintToken, uint minUSDCPremium)
external
override
ensure(deadline)
returns(uint[] memory amounts, uint newTokenId)
{
require(path[path.length - 1] == WETH, 'invalid_path');
amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);
require(amounts[amounts.length - 1] >= amountOutMin, "insufficient_output_amount");
{
address[] calldata _path = path;
TransferHelper.safeTransferFrom(
_path[0], msg.sender, UniswapV2Library.pairFor(factory, _path[0], _path[1]), amounts[0]
);
}
newTokenId = _swapAndWrap(path, amounts, protectionPeriod, to, mintToken, minUSDCPremium);
}
function swapTokensForExactETHAndWrap(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline, uint protectionPeriod,
bool mintToken, uint minUSDCPremium)
external
override
ensure(deadline)
returns (uint[] memory amounts, uint newTokenId)
{
require(path[path.length - 1] == WETH, 'invalid_path');
amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path);
require(amounts[0] <= amountInMax, 'excessive_input_amount');
{
address[] calldata _path = path;
TransferHelper.safeTransferFrom(
_path[0], msg.sender, UniswapV2Library.pairFor(factory, _path[0], _path[1]), amounts[0]
);
}
newTokenId = _swapAndWrap(path, amounts, protectionPeriod, to, mintToken, minUSDCPremium);
}
function _swapAndWrap(address[] calldata path, uint[] memory amounts, uint protectionPeriod, address to, bool mintToken, uint minUSDCPremium)
internal
returns (uint newTokenId)
{
address whAsset = whAssets[path[path.length - 1]];
require(whAsset != address(0), 'whAsset_does_not_exist');
_swap(amounts, path, whAsset);
newTokenId = IWHAssetv2(whAsset).wrapAfterSwap(amounts[amounts.length - 1], protectionPeriod, to, mintToken, minUSDCPremium);
}
function _swap(uint[] memory amounts, address[] memory path, address _to) internal virtual {
for(uint i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0, ) = UniswapV2Library.sortTokens(input, output);
uint amountOut = amounts[i + 1];
(uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0));
address to = i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2]) : _to;
IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output)).swap(
amount0Out, amount1Out, to, new bytes(0)
);
}
}
function quote(uint amountA, uint reserveA, uint reserveB) public pure virtual override returns (uint amountB) {
return UniswapV2Library.quote(amountA, reserveA, reserveB);
}
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut)
public
pure
virtual
override
returns (uint amountOut)
{
return UniswapV2Library.getAmountOut(amountIn, reserveIn, reserveOut);
}
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut)
public
pure
virtual
override
returns (uint amountIn)
{
return UniswapV2Library.getAmountIn(amountOut, reserveIn, reserveOut);
}
function getAmountsOut(uint amountIn, address[] memory path)
public
view
virtual
override
returns (uint[] memory amounts)
{
return UniswapV2Library.getAmountsOut(factory, amountIn, path);
}
function getAmountsIn(uint amountOut, address[] memory path)
public
view
virtual
override
returns (uint[] memory amounts)
{
return UniswapV2Library.getAmountsIn(factory, amountOut, path);
}
modifier ensure(uint deadline) {
require(deadline >= block.timestamp, 'EXPIRED');
_;
}
}
文件 54 的 58:WhiteKeep3r.sol
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "./Governable.sol";
import "./CollectableDust.sol";
import "../Interfaces/IWHAsset.sol";
import "../Interfaces/Keep3r/IKeep3rV1.sol";
import "../Interfaces/Keep3r/IChainLinkFeed.sol";
import "../Interfaces/Keep3r/IKeep3rV1Helper.sol";
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
contract WhiteKeep3r is Governable, CollectableDust {
using Address for address;
using SafeMath for uint256;
using SafeERC20 for IERC20;
IKeep3rV1 public keep3r = IKeep3rV1(0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44);
IChainLinkFeed public immutable ETHUSD = IChainLinkFeed(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);
IChainLinkFeed public constant FASTGAS = IChainLinkFeed(0x169E633A2D1E6c10dD91238Ba11c4A708dfEF37C);
uint public constant gasUsed = 100_000;
address public job;
IERC20 public immutable token;
constructor(IERC20 _token) public Governable(msg.sender) CollectableDust() {
token = _token;
}
function unwrapAll(address whAsset, uint[] calldata tokenIds) external paysKeeper(tokenIds) {
IWHAssetv2(whAsset).autoUnwrapAll(tokenIds, address(this));
}
function refillCredit() external onlyGovernor {
uint balance = token.balanceOf(address(this));
keep3r.addCredit(address(token), job, balance);
}
function _isKeeper() internal {
require(tx.origin == msg.sender, "keep3r::isKeeper:keeper-is-a-smart-contract");
require(keep3r.isKeeper(msg.sender), "keep3r::isKeeper:keeper-is-not-registered");
}
function getRequestedPayment() public view returns(uint){
uint256 gasPrice = Math.min(tx.gasprice, uint256(FASTGAS.latestAnswer()));
return gasPrice.mul(gasUsed).mul(uint(ETHUSD.latestAnswer())).div(1e20);
}
function getRequestedPaymentETH() public view returns(uint){
uint256 gasPrice = Math.min(tx.gasprice, uint256(FASTGAS.latestAnswer()));
return gasPrice.mul(gasUsed);
}
function setJob(address newJob) external onlyGovernor {
job = newJob;
}
modifier paysKeeper(uint[] calldata tokenIds) {
_isKeeper();
_;
uint paidReward = tokenIds.length.mul(getRequestedPayment());
keep3r.receipt(address(token), msg.sender, paidReward);
}
function setKeep3r(address _keep3r) external onlyGovernor {
token.safeApprove(address(keep3r), 0);
keep3r = IKeep3rV1(_keep3r);
token.safeApprove(address(_keep3r), type(uint256).max);
}
function setPendingGovernor(address _pendingGovernor) external override onlyGovernor {
_setPendingGovernor(_pendingGovernor);
}
function acceptGovernor() external override onlyPendingGovernor {
_acceptGovernor();
}
function sendDust(
address _to,
address _token,
uint256 _amount
) external override onlyGovernor {
_sendDust(_to, _token, _amount);
}
}
文件 55 的 58:WhiteOptionsPricer.sol
import "./Interfaces/IWhiteOptionsPricer.sol";
pragma solidity 0.6.12;
contract WhiteOptionsPricer is IWhiteOptionsPricer, Ownable {
using SafeMath for uint;
uint256 public impliedVolRate;
uint256 internal constant PRICE_DECIMALS = 1e8;
AggregatorV3Interface public underlyingPriceProvider;
constructor(AggregatorV3Interface _priceProvider) public {
underlyingPriceProvider = _priceProvider;
impliedVolRate = 5500;
}
function setImpliedVolRate(uint256 value) external onlyOwner {
require(value >= 1000, "ImpliedVolRate limit is too small");
impliedVolRate = value;
}
function getOptionPrice(
uint256 period,
uint256 amount,
uint256
)
external
override
view
returns (uint256 total)
{
require(period <= 4 weeks, "!period: too long");
require(period >= 1 days, "!period: too short");
return amount
.mul(sqrt(period))
.mul(impliedVolRate)
.div(PRICE_DECIMALS);
}
function getAmountToWrapFromTotal(uint total, uint period) external view override returns (uint){
uint numerator = total.mul(PRICE_DECIMALS).mul(10000);
uint denominator = PRICE_DECIMALS.add(sqrt(period).mul(impliedVolRate));
return numerator.div(denominator).div(10000);
}
function sqrt(uint256 x) internal pure returns (uint256 result) {
result = x;
uint256 k = (x + 1) >> 1;
while (k < result) (result, k) = (k, (x / k + k) >> 1);
}
}
文件 56 的 58:WhiteStaking.sol
import "../Interfaces/IWhiteStakingERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
pragma solidity 0.6.12;
abstract
contract WhiteStaking is ERC20, IWhiteStaking {
using SafeERC20 for IERC20;
using SafeMath for uint;
IERC20 public immutable WHITE;
uint internal constant ACCURACY = 1e30;
address payable public immutable FALLBACK_RECIPIENT;
uint public totalProfit = 0;
mapping(address => uint) internal lastProfit;
mapping(address => uint) internal savedProfit;
uint256 public lockupPeriod = 1 days;
mapping(address => uint256) public lastStakeTimestamp;
mapping(address => bool) public _revertTransfersInLockUpPeriod;
constructor(ERC20 _token, string memory name, string memory short)
public ERC20(name, short)
{
WHITE = _token;
FALLBACK_RECIPIENT = msg.sender;
}
function claimProfit() external override returns (uint profit) {
profit = saveProfit(msg.sender);
require(profit > 0, "Zero profit");
savedProfit[msg.sender] = 0;
_transferProfit(profit);
emit Claim(msg.sender, profit);
}
function deposit(uint amount) external override {
lastStakeTimestamp[msg.sender] = block.timestamp;
require(amount > 0, "!amount");
WHITE.safeTransferFrom(msg.sender, address(this), amount);
_mint(msg.sender, amount);
}
function withdraw(uint amount) external lockupFree override {
_burn(msg.sender, amount);
WHITE.safeTransfer(msg.sender, amount);
}
function revertTransfersInLockUpPeriod(bool value) external {
_revertTransfersInLockUpPeriod[msg.sender] = value;
}
function profitOf(address account) external view override returns (uint) {
return savedProfit[account].add(getUnsaved(account));
}
function getUnsaved(address account) internal view returns (uint profit) {
return totalProfit.sub(lastProfit[account]).mul(balanceOf(account)).div(ACCURACY);
}
function saveProfit(address account) internal returns (uint profit) {
uint unsaved = getUnsaved(account);
lastProfit[account] = totalProfit;
profit = savedProfit[account].add(unsaved);
savedProfit[account] = profit;
}
function _beforeTokenTransfer(address from, address to, uint256) internal override {
if (from != address(0)) saveProfit(from);
if (to != address(0)) saveProfit(to);
if (
lastStakeTimestamp[from].add(lockupPeriod) > block.timestamp &&
lastStakeTimestamp[from] > lastStakeTimestamp[to]
) {
require(
!_revertTransfersInLockUpPeriod[to],
"the recipient does not accept blocked funds"
);
lastStakeTimestamp[to] = lastStakeTimestamp[from];
}
}
function _transferProfit(uint amount) internal virtual;
modifier lockupFree {
require(
lastStakeTimestamp[msg.sender].add(lockupPeriod) <= block.timestamp,
"Action suspended due to lockup"
);
_;
}
}
文件 57 的 58:WhiteStakingUSDC.sol
import "./WhiteStaking.sol";
pragma solidity 0.6.12;
contract WhiteStakingUSDC is WhiteStaking, IWhiteStakingERC20 {
using SafeERC20 for IERC20;
using SafeMath for uint;
IERC20 public immutable USDC;
constructor(ERC20 _token, ERC20 usdc) public
WhiteStaking(_token, "Staked WHITE", "sWHITE") {
USDC = usdc;
}
function sendProfit(uint amount) external override {
uint _totalSupply = totalSupply();
if (_totalSupply > 0) {
totalProfit += amount.mul(ACCURACY) / _totalSupply;
USDC.safeTransferFrom(msg.sender, address(this), amount);
emit Profit(amount);
} else {
USDC.safeTransferFrom(msg.sender, FALLBACK_RECIPIENT, amount);
}
}
function _transferProfit(uint amount) internal override {
USDC.safeTransfer(msg.sender, amount);
}
}
文件 58 的 58:WhiteUSDCPool.sol
pragma solidity 0.6.12;
import "./Interfaces/IWhiteUSDCPool.sol";
import "./Interfaces/IWhiteStakingERC20.sol";
contract WhiteUSDCPool is
IWhiteUSDCPool,
Ownable,
ERC20("Whiteheart USDC LP Token", "writeUSDC")
{
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public override immutable token;
IWhiteStakingERC20 public immutable settlementFeeRecipient;
address public hegicFeeRecipient;
uint256 public owedToKeep3r = 0;
uint256 public lockedAmount;
uint256 public lockedPremium;
uint256 public lockupPeriod = 2 weeks;
uint256 public hegicFee = 0;
uint256 public constant INITIAL_RATE = 1e13;
mapping(address => bool) public whAssets;
mapping(address => uint256) public lastProvideTimestamp;
mapping(address => mapping(uint => LockedLiquidity)) public lockedLiquidity;
mapping(address => bool) public _revertTransfersInLockUpPeriod;
constructor(IERC20 _token, IWhiteStakingERC20 _settlementFeeRecipient) public {
token = _token;
settlementFeeRecipient = _settlementFeeRecipient;
hegicFeeRecipient = msg.sender;
IERC20(_token).safeApprove(address(_settlementFeeRecipient), type(uint256).max);
}
modifier onlyWHAssets {
require(whAssets[msg.sender], "whiteheart::pool::not-allowed");
_;
}
function setLockupPeriod(uint256 value) external override onlyOwner {
require(value <= 60 days, "Lockup period is too large");
lockupPeriod = value;
}
function setHegicFeeRecipient(address value) external onlyOwner {
require(value != address(0));
hegicFeeRecipient = value;
}
function withdrawHegicFee() external {
token.safeTransfer(hegicFeeRecipient, hegicFee);
hegicFee = 0;
}
function setAllowedWHAsset(address _whAsset, bool approved) external override onlyOwner {
whAssets[_whAsset] = approved;
}
function revertTransfersInLockUpPeriod(bool value) external {
_revertTransfersInLockUpPeriod[msg.sender] = value;
}
function lock(uint id, uint256 amountToLock, uint256 totalFee) external override onlyWHAssets {
address creator = msg.sender;
require(
lockedAmount.add(amountToLock).mul(10) <= totalBalance().mul(8),
"Pool Error: Amount is too large."
);
uint256 premium = totalFee.mul(30).div(100);
uint256 settlementFee = totalFee.mul(30).div(100);
uint256 hegicFeeAmount = totalFee.sub(premium).sub(settlementFee);
lockedLiquidity[creator][id] = (LockedLiquidity(uint120(amountToLock), uint120(premium), true));
lockedPremium = lockedPremium.add(premium);
lockedAmount = lockedAmount.add(amountToLock);
settlementFeeRecipient.sendProfit(settlementFee);
hegicFee = hegicFee.add(hegicFeeAmount);
}
function unlock(uint256 id) external override {
LockedLiquidity storage ll = lockedLiquidity[msg.sender][id];
require(ll.locked, "LockedLiquidity with such id has already unlocked");
ll.locked = false;
lockedPremium = lockedPremium.sub(ll.premium);
lockedAmount = lockedAmount.sub(ll.amount);
emit Profit(id, ll.premium);
}
function payKeep3r(address keep3r) external onlyWHAssets override returns (uint amount) {
amount = owedToKeep3r;
owedToKeep3r = 0;
if(amount > 0) token.safeTransfer(keep3r, amount);
}
function send(uint id, address payable to, uint256 amount, uint _payKeep3r)
external
override
{
LockedLiquidity storage ll = lockedLiquidity[msg.sender][id];
require(ll.locked, "LockedLiquidity with such id has already unlocked");
require(to != address(0));
ll.locked = false;
lockedPremium = lockedPremium.sub(ll.premium);
lockedAmount = lockedAmount.sub(ll.amount);
uint transferAmount = amount > ll.amount ? ll.amount : amount;
token.safeTransfer(to, transferAmount.sub(_payKeep3r));
if(_payKeep3r > 0) owedToKeep3r = owedToKeep3r.add(_payKeep3r);
if (transferAmount <= ll.premium)
emit Profit(id, ll.premium - transferAmount);
else
emit Loss(id, transferAmount - ll.premium);
}
function deleteLockedLiquidity(uint id) external override {
delete lockedLiquidity[msg.sender][id];
}
function provide(uint256 amount, uint256 minMint) external returns (uint256 mint) {
lastProvideTimestamp[msg.sender] = block.timestamp;
uint supply = totalSupply();
uint balance = totalBalance();
if (supply > 0 && balance > 0)
mint = amount.mul(supply).div(balance);
else
mint = amount.mul(INITIAL_RATE);
require(mint >= minMint, "Pool: Mint limit is too large");
require(mint > 0, "Pool: Amount is too small");
_mint(msg.sender, mint);
emit Provide(msg.sender, amount, mint);
token.safeTransferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount, uint256 maxBurn) external returns (uint256 burn) {
require(
lastProvideTimestamp[msg.sender].add(lockupPeriod) <= block.timestamp,
"Pool: Withdrawal is locked up"
);
require(
amount <= availableBalance(),
"Pool Error: You are trying to unlock more funds than have been locked for your contract. Please lower the amount."
);
burn = divCeil(amount.mul(totalSupply()), totalBalance());
require(burn <= maxBurn, "Pool: Burn limit is too small");
require(burn <= balanceOf(msg.sender), "Pool: Amount is too large");
require(burn > 0, "Pool: Amount is too small");
_burn(msg.sender, burn);
emit Withdraw(msg.sender, amount, burn);
token.safeTransfer(msg.sender, amount);
}
function shareOf(address user) external view returns (uint256 share) {
uint supply = totalSupply();
if (supply > 0)
share = totalBalance().mul(balanceOf(user)).div(supply);
else
share = 0;
}
function availableBalance() public view returns (uint256 balance) {
return totalBalance().sub(lockedAmount);
}
function totalBalance() public override view returns (uint256 balance) {
return token.balanceOf(address(this)).sub(lockedPremium).sub(hegicFee);
}
function _beforeTokenTransfer(address from, address to, uint256) internal override {
if (
lastProvideTimestamp[from].add(lockupPeriod) > block.timestamp &&
lastProvideTimestamp[from] > lastProvideTimestamp[to]
) {
require(
!_revertTransfersInLockUpPeriod[to],
"the recipient does not accept blocked funds"
);
lastProvideTimestamp[to] = lastProvideTimestamp[from];
}
}
function divCeil(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0);
uint256 c = a / b;
if (a % b != 0)
c = c + 1;
return c;
}
}
{
"compilationTarget": {
"contracts/WHAssets/WHETHv2.sol": "WHETHv2"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IUniswapV2Router02","name":"_swapRouter","type":"address"},{"internalType":"contract IToken","name":"_stablecoin","type":"address"},{"internalType":"contract AggregatorV3Interface","name":"_priceProvider","type":"address"},{"internalType":"contract IWhiteUSDCPool","name":"_pool","type":"address"},{"internalType":"contract IWhiteOptionsPricer","name":"_whiteOptionsPricer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint32","name":"tokenId","type":"uint32"},{"indexed":false,"internalType":"uint128","name":"closePrice","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"optionProfit","type":"uint128"}],"name":"Unwrap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint32","name":"tokenId","type":"uint32"},{"indexed":false,"internalType":"uint88","name":"cost","type":"uint88"},{"indexed":false,"internalType":"uint88","name":"amount","type":"uint88"},{"indexed":false,"internalType":"uint48","name":"strike","type":"uint48"},{"indexed":false,"internalType":"uint32","name":"expiration","type":"uint32"}],"name":"Wrap","type":"event"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"rewardRecipient","type":"address"}],"name":"autoUnwrap","outputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"list","type":"uint256[]"},{"internalType":"address","name":"rewardRecipient","type":"address"}],"name":"autoUnwrapAll","outputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"autoUnwrapDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IUniswapV2Router02","name":"_swapRouter","type":"address"}],"name":"connectRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isAutoUnwrapable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keep3r","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"listAutoUnwrapable","outputs":[{"internalType":"uint256[]","name":"list","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"mintToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"optionCollateralizationRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract IWhiteUSDCPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceProvider","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"routers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"disabled","type":"bool"}],"name":"setAutoUnwrapDisabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newKeep3r","type":"address"}],"name":"setKeep3r","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IUniswapV2Router02","name":"newRouter","type":"address"}],"name":"setSwapRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stablecoin","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapRouter","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"underlying","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint88","name":"amount","type":"uint88"},{"internalType":"uint48","name":"expiration","type":"uint48"},{"internalType":"uint48","name":"strike","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"underlyingToStableSwapPath","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"unwrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whiteOptionsPricer","outputs":[{"internalType":"contract IWhiteOptionsPricer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint256","name":"period","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"_mintToken","type":"bool"},{"internalType":"uint256","name":"minPremiumUSDC","type":"uint256"}],"name":"wrap","outputs":[{"internalType":"uint256","name":"newTokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"protectionPeriod","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"mintToken","type":"bool"},{"internalType":"uint256","name":"minUSDCPremium","type":"uint256"}],"name":"wrapAfterSwap","outputs":[{"internalType":"uint256","name":"newTokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"name":"wrapCost","outputs":[{"internalType":"uint256","name":"cost","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]