pragma solidity >=0.6.0 <0.7.0;
import "@openzeppelin/contracts-upgradeable/introspection/IERC1820RegistryUpgradeable.sol";
library Constants {
IERC1820RegistryUpgradeable public constant REGISTRY = IERC1820RegistryUpgradeable(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
// keccak256("ERC777TokensSender")
bytes32 public constant TOKENS_SENDER_INTERFACE_HASH =
0x29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe895;
// keccak256("ERC777TokensRecipient")
bytes32 public constant TOKENS_RECIPIENT_INTERFACE_HASH =
0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b;
// keccak256(abi.encodePacked("ERC1820_ACCEPT_MAGIC"));
bytes32 public constant ACCEPT_MAGIC =
0xa2ef4600d742022d532d4747cb3547474667d6f13804902513b2ec01c848f4b4;
bytes4 public constant ERC165_INTERFACE_ID_ERC165 = 0x01ffc9a7;
bytes4 public constant ERC165_INTERFACE_ID_ERC721 = 0x80ac58cd;
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../proxy/Initializable.sol";
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
uint256[50] private __gap;
}
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.7.0;
library ExtendedSafeCast {
/**
* @dev Converts an unsigned uint256 into a unsigned uint112.
*
* Requirements:
*
* - input must be less than or equal to maxUint112.
*/
function toUint112(uint256 value) internal pure returns (uint112) {
require(value < 2**112, "SafeCast: value doesn't fit in an uint112");
return uint112(value);
}
/**
* @dev Converts an unsigned uint256 into a unsigned uint96.
*
* Requirements:
*
* - input must be less than or equal to maxUint96.
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value < 2**96, "SafeCast: value doesn't fit in an uint96");
return uint96(value);
}
}
/**
Copyright 2020 PoolTogether Inc.
This file is part of PoolTogether.
PoolTogether is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation under version 3 of the License.
PoolTogether is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PoolTogether. If not, see <https://www.gnu.org/licenses/>.
*/
pragma solidity >=0.6.0 <0.8.0;
import "./external/openzeppelin/OpenZeppelinSafeMath_V3_3_0.sol";
/**
* @author Brendan Asselstine
* @notice Provides basic fixed point math calculations.
*
* This library calculates integer fractions by scaling values by 1e18 then performing standard integer math.
*/
library FixedPoint {
using OpenZeppelinSafeMath_V3_3_0 for uint256;
// The scale to use for fixed point numbers. Same as Ether for simplicity.
uint256 internal constant SCALE = 1e18;
/**
* Calculates a Fixed18 mantissa given the numerator and denominator
*
* The mantissa = (numerator * 1e18) / denominator
*
* @param numerator The mantissa numerator
* @param denominator The mantissa denominator
* @return The mantissa of the fraction
*/
function calculateMantissa(uint256 numerator, uint256 denominator) internal pure returns (uint256) {
uint256 mantissa = numerator.mul(SCALE);
mantissa = mantissa.div(denominator);
return mantissa;
}
/**
* Multiplies a Fixed18 number by an integer.
*
* @param b The whole integer to multiply
* @param mantissa The Fixed18 number
* @return An integer that is the result of multiplying the params.
*/
function multiplyUintByMantissa(uint256 b, uint256 mantissa) internal pure returns (uint256) {
uint256 result = mantissa.mul(b);
result = result.div(SCALE);
return result;
}
/**
* Divides an integer by a fixed point 18 mantissa
*
* @param dividend The integer to divide
* @param mantissa The fixed point 18 number to serve as the divisor
* @return An integer that is the result of dividing an integer by a fixed point 18 mantissa
*/
function divideUintByMantissa(uint256 dividend, uint256 mantissa) internal pure returns (uint256) {
uint256 result = SCALE.mul(dividend);
result = result.div(mantissa);
return result;
}
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165Upgradeable {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the global ERC1820 Registry, as defined in the
* https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register
* implementers for interfaces in this registry, as well as query support.
*
* Implementers may be shared by multiple accounts, and can also implement more
* than a single interface for each account. Contracts can implement interfaces
* for themselves, but externally-owned accounts (EOA) must delegate this to a
* contract.
*
* {IERC165} interfaces can also be queried via the registry.
*
* For an in-depth explanation and source code analysis, see the EIP text.
*/
interface IERC1820RegistryUpgradeable {
/**
* @dev Sets `newManager` as the manager for `account`. A manager of an
* account is able to set interface implementers for it.
*
* By default, each account is its own manager. Passing a value of `0x0` in
* `newManager` will reset the manager to this initial state.
*
* Emits a {ManagerChanged} event.
*
* Requirements:
*
* - the caller must be the current manager for `account`.
*/
function setManager(address account, address newManager) external;
/**
* @dev Returns the manager for `account`.
*
* See {setManager}.
*/
function getManager(address account) external view returns (address);
/**
* @dev Sets the `implementer` contract as ``account``'s implementer for
* `interfaceHash`.
*
* `account` being the zero address is an alias for the caller's address.
* The zero address can also be used in `implementer` to remove an old one.
*
* See {interfaceHash} to learn how these are created.
*
* Emits an {InterfaceImplementerSet} event.
*
* Requirements:
*
* - the caller must be the current manager for `account`.
* - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not
* end in 28 zeroes).
* - `implementer` must implement {IERC1820Implementer} and return true when
* queried for support, unless `implementer` is the caller. See
* {IERC1820Implementer-canImplementInterfaceForAddress}.
*/
function setInterfaceImplementer(address account, bytes32 _interfaceHash, address implementer) external;
/**
* @dev Returns the implementer of `interfaceHash` for `account`. If no such
* implementer is registered, returns the zero address.
*
* If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28
* zeroes), `account` will be queried for support of it.
*
* `account` being the zero address is an alias for the caller's address.
*/
function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address);
/**
* @dev Returns the interface hash for an `interfaceName`, as defined in the
* corresponding
* https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].
*/
function interfaceHash(string calldata interfaceName) external pure returns (bytes32);
/**
* @notice Updates the cache with whether the contract implements an ERC165 interface or not.
* @param account Address of the contract for which to update the cache.
* @param interfaceId ERC165 interface for which to update the cache.
*/
function updateERC165Cache(address account, bytes4 interfaceId) external;
/**
* @notice Checks whether a contract implements an ERC165 interface or not.
* If the result is not cached a direct lookup on the contract address is performed.
* If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
* {updateERC165Cache} with the contract address.
* @param account Address of the contract to check.
* @param interfaceId ERC165 interface to check.
* @return True if `account` implements `interfaceId`, false otherwise.
*/
function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);
/**
* @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
* @param account Address of the contract to check.
* @param interfaceId ERC165 interface to check.
* @return True if `account` implements `interfaceId`, false otherwise.
*/
function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);
event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);
event ManagerChanged(address indexed account, address indexed newManager);
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// SPDX-License-Identifier: MIT
// solhint-disable-next-line compiler-version
pragma solidity >=0.4.24 <0.8.0;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/// @dev Returns true if and only if the function is running in the constructor
function _isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
// solhint-disable-next-line no-inline-assembly
assembly { cs := extcodesize(self) }
return cs == 0;
}
}
// SPDX-License-Identifier: MIT
// NOTE: Copied from OpenZeppelin Contracts version 3.3.0
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library OpenZeppelinSafeMath_V3_3_0 {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../GSN/ContextUpgradeable.sol";
import "../proxy/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[49] private __gap;
}
pragma solidity >=0.6.0 <0.7.0;
// solium-disable security/no-inline-assembly
// solium-disable security/no-low-level-calls
contract ProxyFactory {
event ProxyCreated(address proxy);
function deployMinimal(address _logic, bytes memory _data) public returns (address proxy) {
// Adapted from https://github.com/optionality/clone-factory/blob/32782f82dfc5a00d103a7e61a17a5dedbd1e8e9d/contracts/CloneFactory.sol
bytes20 targetBytes = bytes20(_logic);
assembly {
let clone := mload(0x40)
mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(clone, 0x14), targetBytes)
mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
proxy := create(0, clone, 0x37)
}
emit ProxyCreated(address(proxy));
if(_data.length > 0) {
(bool success,) = proxy.call(_data);
require(success, "ProxyFactory/constructor-call-failed");
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCastUpgradeable {
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
require(value < 2**255, "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMathUpgradeable {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.7.0;
import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/SafeCastUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import "@pooltogether/fixed-point/contracts/FixedPoint.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "../utils/ExtendedSafeCast.sol";
import "../token/TokenListener.sol";
/// @title Disburses a token at a fixed rate per second to holders of another token.
/// @notice The tokens are dripped at a "drip rate per second". This is the number of tokens that
/// are dripped each second. A user's share of the dripped tokens is based on how many 'measure' tokens they hold.
/* solium-disable security/no-block-members */
contract TokenFaucet is OwnableUpgradeable, TokenListener {
using SafeMathUpgradeable for uint256;
using SafeCastUpgradeable for uint256;
using ExtendedSafeCast for uint256;
event Initialized(
IERC20Upgradeable indexed asset,
IERC20Upgradeable indexed measure,
uint256 dripRatePerSecond
);
event Dripped(
uint256 newTokens
);
event Deposited(
address indexed user,
uint256 amount
);
event Claimed(
address indexed user,
uint256 newTokens
);
event DripRateChanged(
uint256 dripRatePerSecond
);
struct UserState {
uint128 lastExchangeRateMantissa;
uint128 balance;
}
/// @notice The token that is being disbursed
IERC20Upgradeable public asset;
/// @notice The token that is user to measure a user's portion of disbursed tokens
IERC20Upgradeable public measure;
/// @notice The total number of tokens that are disbursed each second
uint256 public dripRatePerSecond;
/// @notice The cumulative exchange rate of measure token supply : dripped tokens
uint112 public exchangeRateMantissa;
/// @notice The total amount of tokens that have been dripped but not claimed
uint112 public totalUnclaimed;
/// @notice The timestamp at which the tokens were last dripped
uint32 public lastDripTimestamp;
/// @notice The data structure that tracks when a user last received tokens
mapping(address => UserState) public userStates;
/// @notice Initializes a new Comptroller V2
/// @param _asset The asset to disburse to users
/// @param _measure The token to use to measure a users portion
/// @param _dripRatePerSecond The amount of the asset to drip each second
function initialize (
IERC20Upgradeable _asset,
IERC20Upgradeable _measure,
uint256 _dripRatePerSecond
) public initializer {
__Ownable_init();
lastDripTimestamp = _currentTime();
asset = _asset;
measure = _measure;
setDripRatePerSecond(_dripRatePerSecond);
emit Initialized(
asset,
measure,
dripRatePerSecond
);
}
/// @notice Safely deposits asset tokens into the faucet. Must be pre-approved
/// This should be used instead of transferring directly because the drip function must
/// be called before receiving new assets.
/// @param amount The amount of asset tokens to add (must be approved already)
function deposit(uint256 amount) external {
drip();
asset.transferFrom(msg.sender, address(this), amount);
emit Deposited(msg.sender, amount);
}
/// @notice Transfers all unclaimed tokens to the user
/// @param user The user to claim tokens for
/// @return The amount of tokens that were claimed.
function claim(address user) external returns (uint256) {
drip();
_captureNewTokensForUser(user);
uint256 balance = userStates[user].balance;
userStates[user].balance = 0;
totalUnclaimed = uint256(totalUnclaimed).sub(balance).toUint112();
asset.transfer(user, balance);
emit Claimed(user, balance);
return balance;
}
/// @notice Drips new tokens.
/// @dev Should be called immediately before any measure token mints/transfers/burns
/// @return The number of new tokens dripped.
function drip() public returns (uint256) {
uint256 currentTimestamp = _currentTime();
// this should only run once per block.
if (lastDripTimestamp == uint32(currentTimestamp)) {
return 0;
}
uint256 assetTotalSupply = asset.balanceOf(address(this));
uint256 availableTotalSupply = assetTotalSupply.sub(totalUnclaimed);
uint256 newSeconds = currentTimestamp.sub(lastDripTimestamp);
uint256 nextExchangeRateMantissa = exchangeRateMantissa;
uint256 newTokens;
uint256 measureTotalSupply = measure.totalSupply();
if (measureTotalSupply > 0 && availableTotalSupply > 0) {
newTokens = newSeconds.mul(dripRatePerSecond);
if (newTokens > availableTotalSupply) {
newTokens = availableTotalSupply;
}
uint256 indexDeltaMantissa = FixedPoint.calculateMantissa(newTokens, measureTotalSupply);
nextExchangeRateMantissa = nextExchangeRateMantissa.add(indexDeltaMantissa);
emit Dripped(
newTokens
);
}
exchangeRateMantissa = nextExchangeRateMantissa.toUint112();
totalUnclaimed = uint256(totalUnclaimed).add(newTokens).toUint112();
lastDripTimestamp = currentTimestamp.toUint32();
return newTokens;
}
function setDripRatePerSecond(uint256 _dripRatePerSecond) public onlyOwner {
require(_dripRatePerSecond > 0, "TokenFaucet/dripRate-gt-zero");
// ensure we're all caught up
drip();
dripRatePerSecond = _dripRatePerSecond;
emit DripRateChanged(dripRatePerSecond);
}
/// @notice Captures new tokens for a user
/// @dev This must be called before changes to the user's balance (i.e. before mint, transfer or burns)
/// @param user The user to capture tokens for
/// @return The number of new tokens
function _captureNewTokensForUser(
address user
) private returns (uint128) {
UserState storage userState = userStates[user];
if (exchangeRateMantissa == userState.lastExchangeRateMantissa) {
// ignore if exchange rate is same
return 0;
}
uint256 deltaExchangeRateMantissa = uint256(exchangeRateMantissa).sub(userState.lastExchangeRateMantissa);
uint256 userMeasureBalance = measure.balanceOf(user);
uint128 newTokens = FixedPoint.multiplyUintByMantissa(userMeasureBalance, deltaExchangeRateMantissa).toUint128();
userStates[user] = UserState({
lastExchangeRateMantissa: exchangeRateMantissa,
balance: uint256(userState.balance).add(newTokens).toUint128()
});
return newTokens;
}
/// @notice Should be called before a user mints new "measure" tokens.
/// @param to The user who is minting the tokens
/// @param amount The amount of tokens they are minting
/// @param token The token they are minting
/// @param referrer The user who referred the minting.
function beforeTokenMint(
address to,
uint256 amount,
address token,
address referrer
)
external
override
{
if (token == address(measure)) {
drip();
_captureNewTokensForUser(to);
}
}
/// @notice Should be called before "measure" tokens are transferred or burned
/// @param from The user who is sending the tokens
/// @param to The user who is receiving the tokens
/// @param token The token token they are burning
function beforeTokenTransfer(
address from,
address to,
uint256,
address token
)
external
override
{
// must be measure and not be minting
if (token == address(measure) && from != address(0)) {
drip();
_captureNewTokensForUser(to);
_captureNewTokensForUser(from);
}
}
/// @notice returns the current time. Allows for override in testing.
/// @return The current time (block.timestamp)
function _currentTime() internal virtual view returns (uint32) {
return block.timestamp.toUint32();
}
}
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.7.0;
import "./TokenFaucet.sol";
import "../external/openzeppelin/ProxyFactory.sol";
/// @title Stake Prize Pool Proxy Factory
/// @notice Minimal proxy pattern for creating new TokenFaucet contracts
contract TokenFaucetProxyFactory is ProxyFactory {
/// @notice Contract template for deploying proxied Comptrollers
TokenFaucet public instance;
/// @notice Initializes the Factory with an instance of the TokenFaucet
constructor () public {
instance = new TokenFaucet();
}
/// @notice Creates a new Comptroller V2
/// @param _asset The asset to disburse to users
/// @param _measure The token to use to measure a users portion
/// @param _dripRatePerSecond The amount of the asset to drip each second
/// @return A reference to the new proxied Comptroller V2
function create(
IERC20Upgradeable _asset,
IERC20Upgradeable _measure,
uint256 _dripRatePerSecond
) external returns (TokenFaucet) {
TokenFaucet comptroller = TokenFaucet(deployMinimal(address(instance), ""));
comptroller.initialize(
_asset, _measure, _dripRatePerSecond
);
comptroller.transferOwnership(msg.sender);
return comptroller;
}
/// @notice Runs claim on all passed comptrollers for a user.
/// @param user The user to claim for
/// @param comptrollers The comptrollers to call claim on.
function claimAll(address user, TokenFaucet[] calldata comptrollers) external {
for (uint256 i = 0; i < comptrollers.length; i++) {
comptrollers[i].claim(user);
}
}
}
pragma solidity ^0.6.4;
import "./TokenListenerInterface.sol";
import "./TokenListenerLibrary.sol";
import "../Constants.sol";
abstract contract TokenListener is TokenListenerInterface {
function supportsInterface(bytes4 interfaceId) external override view returns (bool) {
return (
interfaceId == Constants.ERC165_INTERFACE_ID_ERC165 ||
interfaceId == TokenListenerLibrary.ERC165_INTERFACE_ID_TOKEN_LISTENER
);
}
}
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.7.0;
import "@openzeppelin/contracts-upgradeable/introspection/IERC165Upgradeable.sol";
/// @title An interface that allows a contract to listen to token mint, transfer and burn events.
interface TokenListenerInterface is IERC165Upgradeable {
/// @notice Called when tokens are minted.
/// @param to The address of the receiver of the minted tokens.
/// @param amount The amount of tokens being minted
/// @param controlledToken The address of the token that is being minted
/// @param referrer The address that referred the minting.
function beforeTokenMint(address to, uint256 amount, address controlledToken, address referrer) external;
/// @notice Called when tokens are transferred or burned.
/// @param from The address of the sender of the token transfer
/// @param to The address of the receiver of the token transfer. Will be the zero address if burning.
/// @param amount The amount of tokens transferred
/// @param controlledToken The address of the token that was transferred
function beforeTokenTransfer(address from, address to, uint256 amount, address controlledToken) external;
}
pragma solidity ^0.6.12;
library TokenListenerLibrary {
/*
* bytes4(keccak256('beforeTokenMint(address,uint256,address,address)')) == 0x4d7f3db0
* bytes4(keccak256('beforeTokenTransfer(address,address,uint256,address)')) == 0xb2210957
*
* => 0x4d7f3db0 ^ 0xb2210957 == 0xff5e34e7
*/
bytes4 public constant ERC165_INTERFACE_ID_TOKEN_LISTENER = 0xff5e34e7;
}
{
"compilationTarget": {
"contracts/token-faucet/TokenFaucetProxyFactory.sol": "TokenFaucetProxyFactory"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"proxy","type":"address"}],"name":"ProxyCreated","type":"event"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"contract TokenFaucet[]","name":"comptrollers","type":"address[]"}],"name":"claimAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Upgradeable","name":"_asset","type":"address"},{"internalType":"contract IERC20Upgradeable","name":"_measure","type":"address"},{"internalType":"uint256","name":"_dripRatePerSecond","type":"uint256"}],"name":"create","outputs":[{"internalType":"contract TokenFaucet","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"deployMinimal","outputs":[{"internalType":"address","name":"proxy","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"instance","outputs":[{"internalType":"contract TokenFaucet","name":"","type":"address"}],"stateMutability":"view","type":"function"}]