¡El código fuente de este contrato está verificado!
Metadatos del Contrato
Compilador
0.8.7+commit.e28d00a7
Idioma
Solidity
Código Fuente del Contrato
Archivo 1 de 39: Address.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @dev Collection of functions related to the address type
*/libraryAddress{
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/functionisContract(address account) internalviewreturns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in// construction, since the code is only stored at the end of the// constructor execution.uint256 size;
assembly {
size :=extcodesize(account)
}
return size >0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/functionsendValue(addresspayable 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");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/functionfunctionCall(address target, bytesmemory data) internalreturns (bytesmemory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/functionfunctionCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value
) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value,
stringmemory errorMessage
) internalreturns (bytesmemory) {
require(address(this).balance>= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytesmemory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/functionfunctionStaticCall(address target, bytesmemory data) internalviewreturns (bytesmemory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/functionfunctionStaticCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalviewreturns (bytesmemory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytesmemory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target, bytesmemory data) internalreturns (bytesmemory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytesmemory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/functionverifyCallResult(bool success,
bytesmemory returndata,
stringmemory errorMessage
) internalpurereturns (bytesmemory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if presentif (returndata.length>0) {
// The easiest way to bubble the revert reason is using memory via assemblyassembly {
let returndata_size :=mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/libraryEnumerableSet{
// To implement this library for multiple types with as little code// repetition as possible, we write it in terms of a generic Set type with// bytes32 values.// The Set implementation uses private functions, and user-facing// implementations (such as AddressSet) are just wrappers around the// underlying Set.// This means that we can only create new EnumerableSets for types that fit// in bytes32.structSet {
// Storage of set valuesbytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0// means a value is not in the set.mapping(bytes32=>uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/function_add(Set storage set, bytes32 value) privatereturns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/function_remove(Set storage set, bytes32 value) privatereturns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slotuint256 valueIndex = set._indexes[value];
if (valueIndex !=0) {
// Equivalent to contains(set, value)// To delete an element from the _values array in O(1), we swap the element to delete with the last one in// the array, and then remove the last element (sometimes called as 'swap and pop').// This modifies the order of the array, as noted in {at}.uint256 toDeleteIndex = valueIndex -1;
uint256 lastIndex = set._values.length-1;
if (lastIndex != toDeleteIndex) {
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slotdelete set._indexes[value];
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/function_contains(Set storage set, bytes32 value) privateviewreturns (bool) {
return set._indexes[value] !=0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/function_length(Set storage set) privateviewreturns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/function_at(Set storage set, uint256 index) privateviewreturns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/function_values(Set storage set) privateviewreturns (bytes32[] memory) {
return set._values;
}
// Bytes32SetstructBytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(Bytes32Set storage set, bytes32 value) internalreturns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(Bytes32Set storage set, bytes32 value) internalreturns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(Bytes32Set storage set, bytes32 value) internalviewreturns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/functionlength(Bytes32Set storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(Bytes32Set storage set, uint256 index) internalviewreturns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(Bytes32Set storage set) internalviewreturns (bytes32[] memory) {
return _values(set._inner);
}
// AddressSetstructAddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(AddressSet storage set, address value) internalreturns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(AddressSet storage set, address value) internalreturns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(AddressSet storage set, address value) internalviewreturns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/functionlength(AddressSet storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(AddressSet storage set, uint256 index) internalviewreturns (address) {
returnaddress(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(AddressSet storage set) internalviewreturns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
// UintSetstructUintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(UintSet storage set, uint256 value) internalreturns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(UintSet storage set, uint256 value) internalreturns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(UintSet storage set, uint256 value) internalviewreturns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/functionlength(UintSet storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(UintSet storage set, uint256 index) internalviewreturns (uint256) {
returnuint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(UintSet storage set) internalviewreturns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
Código Fuente del Contrato
Archivo 4 de 39: FullMath.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;/// @title Contains 512-bit math functions/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bitslibraryFullMath{
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0/// @param a The multiplicand/// @param b The multiplier/// @param denominator The divisor/// @return result The 256-bit result/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldivfunctionmulDiv(uint256 a,
uint256 b,
uint256 denominator
) internalpurereturns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = a * b// Compute the product mod 2**256 and mod 2**256 - 1// then use the Chinese Remainder Theorem to reconstruct// the 512 bit result. The result is stored in two 256// variables such that product = prod1 * 2**256 + prod0uint256 prod0; // Least significant 256 bits of the productuint256 prod1; // Most significant 256 bits of the productassembly {
let mm :=mulmod(a, b, not(0))
prod0 :=mul(a, b)
prod1 :=sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 divisionif (prod1 ==0) {
require(denominator >0);
assembly {
result :=div(prod0, denominator)
}
return result;
}
// Make sure the result is less than 2**256.// Also prevents denominator == 0require(denominator > prod1);
///////////////////////////////////////////////// 512 by 256 division.///////////////////////////////////////////////// Make division exact by subtracting the remainder from [prod1 prod0]// Compute remainder using mulmoduint256 remainder;
assembly {
remainder :=mulmod(a, b, denominator)
}
// Subtract 256 bit number from 512 bit numberassembly {
prod1 :=sub(prod1, gt(remainder, prod0))
prod0 :=sub(prod0, remainder)
}
// Factor powers of two out of denominator// Compute largest power of two divisor of denominator.// Always >= 1.uint256 twos = (~denominator +1) & denominator;
// Divide denominator by power of twoassembly {
denominator :=div(denominator, twos)
}
// Divide [prod1 prod0] by the factors of twoassembly {
prod0 :=div(prod0, twos)
}
// Shift in bits from prod1 into prod0. For this we need// to flip `twos` such that it is 2**256 / twos.// If twos is zero, then it becomes oneassembly {
twos :=add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
// Invert denominator mod 2**256// Now that denominator is an odd number, it has an inverse// modulo 2**256 such that denominator * inv = 1 mod 2**256.// Compute the inverse by starting with a seed that is correct// correct for four bits. That is, denominator * inv = 1 mod 2**4uint256 inv = (3* denominator) ^2;
// Now use Newton-Raphson iteration to improve the precision.// Thanks to Hensel's lifting lemma, this also works in modular// arithmetic, doubling the correct bits in each step.
inv *=2- denominator * inv; // inverse mod 2**8
inv *=2- denominator * inv; // inverse mod 2**16
inv *=2- denominator * inv; // inverse mod 2**32
inv *=2- denominator * inv; // inverse mod 2**64
inv *=2- denominator * inv; // inverse mod 2**128
inv *=2- denominator * inv; // inverse mod 2**256// Because the division is now exact we can divide by multiplying// with the modular inverse of denominator. This will give us the// correct result modulo 2**256. Since the precoditions guarantee// that the outcome is less than 2**256, this is the final result.// We don't need to compute the high bits of the result and prod1// is no longer required.
result = prod0 * inv;
return result;
}
}
/// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0/// @param a The multiplicand/// @param b The multiplier/// @param denominator The divisor/// @return result The 256-bit resultfunctionmulDivRoundingUp(uint256 a,
uint256 b,
uint256 denominator
) internalpurereturns (uint256 result) {
unchecked {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) >0) {
require(result <type(uint256).max);
result++;
}
}
}
}
Código Fuente del Contrato
Archivo 5 de 39: Governable.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;import'../../interfaces/peripherals/IGovernable.sol';
abstractcontractGovernableisIGovernable{
/// @inheritdoc IGovernableaddresspublicoverride governance;
/// @inheritdoc IGovernableaddresspublicoverride pendingGovernance;
constructor(address _governance) {
if (_governance ==address(0)) revert NoGovernanceZeroAddress();
governance = _governance;
}
/// @inheritdoc IGovernablefunctionsetGovernance(address _governance) externaloverrideonlyGovernance{
pendingGovernance = _governance;
emit GovernanceProposal(_governance);
}
/// @inheritdoc IGovernablefunctionacceptGovernance() externaloverrideonlyPendingGovernance{
governance = pendingGovernance;
delete pendingGovernance;
emit GovernanceSet(governance);
}
/// @notice Functions with this modifier can only be called by governancemodifieronlyGovernance{
if (msg.sender!= governance) revert OnlyGovernance();
_;
}
/// @notice Functions with this modifier can only be called by pendingGovernancemodifieronlyPendingGovernance{
if (msg.sender!= pendingGovernance) revert OnlyPendingGovernance();
_;
}
}
Código Fuente del Contrato
Archivo 6 de 39: IBaseErrors.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;interfaceIBaseErrors{
/// @notice Throws if a variable is assigned to the zero addresserrorZeroAddress();
}
Código Fuente del Contrato
Archivo 7 de 39: IDustCollector.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;import'./IBaseErrors.sol';
interfaceIDustCollectorisIBaseErrors{
/// @notice Emitted when dust is sent/// @param _token The token that will be transferred/// @param _amount The amount of the token that will be transferred/// @param _to The address which will receive the fundseventDustSent(address _token, uint256 _amount, address _to);
/// @notice Allows an authorized user to transfer the tokens or eth that may have been left in a contract/// @param _token The token that will be transferred/// @param _amount The amount of the token that will be transferred/// @param _to The address that will receive the idle fundsfunctionsendDust(address _token,
uint256 _amount,
address _to
) external;
}
Código Fuente del Contrato
Archivo 8 de 39: IERC20.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/interfaceIERC20{
/**
* @dev Returns the amount of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (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.
*/functiontransfer(address recipient, uint256 amount) externalreturns (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.
*/functionallowance(address owner, address spender) externalviewreturns (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.
*/functionapprove(address spender, uint256 amount) externalreturns (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.
*/functiontransferFrom(address sender,
address recipient,
uint256 amount
) externalreturns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed 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.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
}
Código Fuente del Contrato
Archivo 9 de 39: IERC20Metadata.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/interfaceIERC20MetadataisIERC20{
/**
* @dev Returns the name of the token.
*/functionname() externalviewreturns (stringmemory);
/**
* @dev Returns the symbol of the token.
*/functionsymbol() externalviewreturns (stringmemory);
/**
* @dev Returns the decimals places of the token.
*/functiondecimals() externalviewreturns (uint8);
}
Código Fuente del Contrato
Archivo 10 de 39: IGovernable.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;/// @title Governable contract/// @notice Manages the governance roleinterfaceIGovernable{
// Events/// @notice Emitted when pendingGovernance accepts to be governance/// @param _governance Address of the new governanceeventGovernanceSet(address _governance);
/// @notice Emitted when a new governance is proposed/// @param _pendingGovernance Address that is proposed to be the new governanceeventGovernanceProposal(address _pendingGovernance);
// Errors/// @notice Throws if the caller of the function is not governanceerrorOnlyGovernance();
/// @notice Throws if the caller of the function is not pendingGovernanceerrorOnlyPendingGovernance();
/// @notice Throws if trying to set governance to zero addresserrorNoGovernanceZeroAddress();
// Variables/// @notice Stores the governance address/// @return _governance The governance addresssfunctiongovernance() externalviewreturns (address _governance);
/// @notice Stores the pendingGovernance address/// @return _pendingGovernance The pendingGovernance addresssfunctionpendingGovernance() externalviewreturns (address _pendingGovernance);
// Methods/// @notice Proposes a new address to be governance/// @param _governance The address being proposed as the new governancefunctionsetGovernance(address _governance) external;
/// @notice Changes the governance from the current governance to the previously proposed addressfunctionacceptGovernance() external;
}
Código Fuente del Contrato
Archivo 11 de 39: IKeep3rAccountance.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;/// @title Keep3rDisputable contract/// @notice Disputes keepers, or if they're already disputed, it can resolve the case/// @dev Argument `bonding` can be the address of either a token or a liquidityinterfaceIKeep3rAccountance{
// Events/// @notice Emitted when the bonding process of a new keeper begins/// @param _keeper The caller of Keep3rKeeperFundable#bond function/// @param _bonding The asset the keeper has bonded/// @param _amount The amount the keeper has bondedeventBonding(addressindexed _keeper, addressindexed _bonding, uint256 _amount);
/// @notice Emitted when a keeper or job begins the unbonding process to withdraw the funds/// @param _keeperOrJob The keeper or job that began the unbonding process/// @param _unbonding The liquidity pair or asset being unbonded/// @param _amount The amount being unbondedeventUnbonding(addressindexed _keeperOrJob, addressindexed _unbonding, uint256 _amount);
// Variables/// @notice Tracks the total KP3R earnings of a keeper since it started working/// @param _keeper The address of the keeper/// @return _workCompleted Total KP3R earnings of a keeper since it started workingfunctionworkCompleted(address _keeper) externalviewreturns (uint256 _workCompleted);
/// @notice Tracks when a keeper was first registered/// @param _keeper The address of the keeper/// @return timestamp The time at which the keeper was first registeredfunctionfirstSeen(address _keeper) externalviewreturns (uint256 timestamp);
/// @notice Tracks if a keeper or job has a pending dispute/// @param _keeperOrJob The address of the keeper or job/// @return _disputed Whether a keeper or job has a pending disputefunctiondisputes(address _keeperOrJob) externalviewreturns (bool _disputed);
/// @notice Tracks how much a keeper has bonded of a certain token/// @param _keeper The address of the keeper/// @param _bond The address of the token being bonded/// @return _bonds Amount of a certain token that a keeper has bondedfunctionbonds(address _keeper, address _bond) externalviewreturns (uint256 _bonds);
/// @notice The current token credits available for a job/// @param _job The address of the job/// @param _token The address of the token bonded/// @return _amount The amount of token credits available for a jobfunctionjobTokenCredits(address _job, address _token) externalviewreturns (uint256 _amount);
/// @notice Tracks the amount of assets deposited in pending bonds/// @param _keeper The address of the keeper/// @param _bonding The address of the token being bonded/// @return _pendingBonds Amount of a certain asset a keeper has unbondingfunctionpendingBonds(address _keeper, address _bonding) externalviewreturns (uint256 _pendingBonds);
/// @notice Tracks when a bonding for a keeper can be activated/// @param _keeper The address of the keeper/// @param _bonding The address of the token being bonded/// @return _timestamp Time at which the bonding for a keeper can be activatedfunctioncanActivateAfter(address _keeper, address _bonding) externalviewreturns (uint256 _timestamp);
/// @notice Tracks when keeper bonds are ready to be withdrawn/// @param _keeper The address of the keeper/// @param _bonding The address of the token being unbonded/// @return _timestamp Time at which the keeper bonds are ready to be withdrawnfunctioncanWithdrawAfter(address _keeper, address _bonding) externalviewreturns (uint256 _timestamp);
/// @notice Tracks how much keeper bonds are to be withdrawn/// @param _keeper The address of the keeper/// @param _bonding The address of the token being unbonded/// @return _pendingUnbonds The amount of keeper bonds that are to be withdrawnfunctionpendingUnbonds(address _keeper, address _bonding) externalviewreturns (uint256 _pendingUnbonds);
/// @notice Checks whether the address has ever bonded an asset/// @param _keeper The address of the keeper/// @return _hasBonded Whether the address has ever bonded an assetfunctionhasBonded(address _keeper) externalviewreturns (bool _hasBonded);
// Methods/// @notice Lists all jobs/// @return _jobList Array with all the jobs in _jobsfunctionjobs() externalviewreturns (address[] memory _jobList);
/// @notice Lists all keepers/// @return _keeperList Array with all the keepers in _keepersfunctionkeepers() externalviewreturns (address[] memory _keeperList);
// Errors/// @notice Throws when an address is passed as a job, but that address is not a joberrorJobUnavailable();
/// @notice Throws when an action that requires an undisputed job is applied on a disputed joberrorJobDisputed();
}
Código Fuente del Contrato
Archivo 12 de 39: IKeep3rDisputable.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;/// @title Keep3rDisputable contract/// @notice Creates/resolves disputes for jobs or keepers/// A disputed keeper is slashable and is not able to bond, activate, withdraw or receive direct payments/// A disputed job is slashable and is not able to pay the keepers, withdraw tokens or to migrateinterfaceIKeep3rDisputable{
/// @notice Emitted when a keeper or a job is disputed/// @param _jobOrKeeper The address of the disputed keeper/job/// @param _disputer The user that called the function and disputed the keepereventDispute(addressindexed _jobOrKeeper, addressindexed _disputer);
/// @notice Emitted when a dispute is resolved/// @param _jobOrKeeper The address of the disputed keeper/job/// @param _resolver The user that called the function and resolved the disputeeventResolve(addressindexed _jobOrKeeper, addressindexed _resolver);
/// @notice Throws when a job or keeper is already disputederrorAlreadyDisputed();
/// @notice Throws when a job or keeper is not disputed and someone tries to resolve the disputeerrorNotDisputed();
/// @notice Allows governance to create a dispute for a given keeper/job/// @param _jobOrKeeper The address in disputefunctiondispute(address _jobOrKeeper) external;
/// @notice Allows governance to resolve a dispute on a keeper/job/// @param _jobOrKeeper The address clearedfunctionresolve(address _jobOrKeeper) external;
}
Código Fuente del Contrato
Archivo 13 de 39: IKeep3rHelper.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;/// @title Keep3rHelper contract/// @notice Contains all the helper functions used throughout the different files.interfaceIKeep3rHelper{
// Errors/// @notice Throws when none of the tokens in the liquidity pair is KP3RerrorLiquidityPairInvalid();
// Methods// solhint-enable func-name-mixedcase/// @notice Calculates the amount of KP3R that corresponds to the ETH passed into the function/// @dev This function allows us to calculate how much KP3R we should pay to a keeper for things expressed in ETH, like gas/// @param _eth The amount of ETH/// @return _amountOut The amount of KP3Rfunctionquote(uint256 _eth) externalviewreturns (uint256 _amountOut);
/// @notice Returns the amount of KP3R the keeper has bonded/// @param _keeper The address of the keeper to check/// @return _amountBonded The amount of KP3R the keeper has bondedfunctionbonds(address _keeper) externalviewreturns (uint256 _amountBonded);
/// @notice Calculates the reward (in KP3R) that corresponds to a keeper for using gas/// @param _keeper The address of the keeper to check/// @param _gasUsed The amount of gas used that will be rewarded/// @return _kp3r The amount of KP3R that should be awarded to the keeperfunctiongetRewardAmountFor(address _keeper, uint256 _gasUsed) externalviewreturns (uint256 _kp3r);
/// @notice Calculates the boost in the reward given to a keeper based on the amount of KP3R that keeper has bonded/// @param _bonds The amount of KP3R tokens bonded by the keeper/// @return _rewardBoost The reward boost that corresponds to the keeperfunctiongetRewardBoostFor(uint256 _bonds) externalviewreturns (uint256 _rewardBoost);
/// @notice Calculates the reward (in KP3R) that corresponds to tx.origin for using gas/// @param _gasUsed The amount of gas used that will be rewarded/// @return _amount The amount of KP3R that should be awarded to tx.originfunctiongetRewardAmount(uint256 _gasUsed) externalviewreturns (uint256 _amount);
/// @notice Given a pool address, returns the underlying tokens of the pair/// @param _pool Address of the correspondant pool/// @return _token0 Address of the first token of the pair/// @return _token1 Address of the second token of the pairfunctiongetPoolTokens(address _pool) externalviewreturns (address _token0, address _token1);
/// @notice Defines the order of the tokens in the pair for twap calculations/// @param _pool Address of the correspondant pool/// @return _isKP3RToken0 Boolean indicating the order of the tokens in the pairfunctionisKP3RToken0(address _pool) externalviewreturns (bool _isKP3RToken0);
/// @notice Given an array of secondsAgo, returns UniswapV3 pool cumulatives at that moment/// @param _pool Address of the pool to observe/// @param _secondsAgo Array with time references to observe/// @return _tickCumulative1 Cummulative sum of ticks until first time reference/// @return _tickCumulative2 Cummulative sum of ticks until second time reference/// @return _success Boolean indicating if the observe call was succesfullfunctionobserve(address _pool, uint32[] memory _secondsAgo)
externalviewreturns (int56 _tickCumulative1,
int56 _tickCumulative2,
bool _success
);
/// @notice Get multiplier, quote, and extra, in order to calculate keeper payment/// @param _bonds Amount of bonded KP3R owned by the keeper/// @return _boost Multiplier per gas unit. Takes into account the base fee and the amount of bonded KP3R/// @return _oneEthQuote Amount of KP3R tokens equivalent to 1 ETH/// @return _extra Amount of extra gas that should be added to the gas spentfunctiongetPaymentParams(uint256 _bonds)
externalviewreturns (uint256 _boost,
uint256 _oneEthQuote,
uint256 _extra
);
/// @notice Given a tick and a liquidity amount, calculates the underlying KP3R tokens/// @param _liquidityAmount Amount of liquidity to be converted/// @param _tickDifference Tick value used to calculate the quote/// @param _timeInterval Time value used to calculate the quote/// @return _kp3rAmount Amount of KP3R tokens underlying on the given liquidityfunctiongetKP3RsAtTick(uint256 _liquidityAmount,
int56 _tickDifference,
uint256 _timeInterval
) externalpurereturns (uint256 _kp3rAmount);
/// @notice Given a tick and a token amount, calculates the output in correspondant token/// @param _baseAmount Amount of token to be converted/// @param _tickDifference Tick value used to calculate the quote/// @param _timeInterval Time value used to calculate the quote/// @return _quoteAmount Amount of credits deserved for the baseAmount at the tick valuefunctiongetQuoteAtTick(uint128 _baseAmount,
int56 _tickDifference,
uint256 _timeInterval
) externalpurereturns (uint256 _quoteAmount);
}
Código Fuente del Contrato
Archivo 14 de 39: IKeep3rJobs.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;/// @title Keep3rJobFundableCredits contract/// @notice Handles the addition and withdrawal of credits from a jobinterfaceIKeep3rJobFundableCredits{
// Events/// @notice Emitted when Keep3rJobFundableCredits#addTokenCreditsToJob is called/// @param _job The address of the job being credited/// @param _token The address of the token being provided/// @param _provider The user that calls the function/// @param _amount The amount of credit being added to the jobeventTokenCreditAddition(addressindexed _job, addressindexed _token, addressindexed _provider, uint256 _amount);
/// @notice Emitted when Keep3rJobFundableCredits#withdrawTokenCreditsFromJob is called/// @param _job The address of the job from which the credits are withdrawn/// @param _token The credit being withdrawn from the job/// @param _receiver The user that receives the tokens/// @param _amount The amount of credit withdrawneventTokenCreditWithdrawal(addressindexed _job, addressindexed _token, addressindexed _receiver, uint256 _amount);
// Errors/// @notice Throws when the token is KP3R, as it should not be used for direct token paymentserrorTokenUnallowed();
/// @notice Throws when the token withdraw cooldown has not yet passederrorJobTokenCreditsLocked();
/// @notice Throws when the user tries to withdraw more tokens than it haserrorInsufficientJobTokenCredits();
// Variables/// @notice Last block where tokens were added to the job/// @param _job The address of the job credited/// @param _token The address of the token credited/// @return _timestamp The last block where tokens were added to the jobfunctionjobTokenCreditsAddedAt(address _job, address _token) externalviewreturns (uint256 _timestamp);
// Methods/// @notice Add credit to a job to be paid out for work/// @param _job The address of the job being credited/// @param _token The address of the token being credited/// @param _amount The amount of credit being addedfunctionaddTokenCreditsToJob(address _job,
address _token,
uint256 _amount
) external;
/// @notice Withdraw credit from a job/// @param _job The address of the job from which the credits are withdrawn/// @param _token The address of the token being withdrawn/// @param _amount The amount of token to be withdrawn/// @param _receiver The user that will receive tokensfunctionwithdrawTokenCreditsFromJob(address _job,
address _token,
uint256 _amount,
address _receiver
) external;
}
/// @title Keep3rJobFundableLiquidity contract/// @notice Handles the funding of jobs through specific liquidity pairsinterfaceIKeep3rJobFundableLiquidity{
// Events/// @notice Emitted when Keep3rJobFundableLiquidity#approveLiquidity function is called/// @param _liquidity The address of the liquidity pair being approvedeventLiquidityApproval(address _liquidity);
/// @notice Emitted when Keep3rJobFundableLiquidity#revokeLiquidity function is called/// @param _liquidity The address of the liquidity pair being revokedeventLiquidityRevocation(address _liquidity);
/// @notice Emitted when IKeep3rJobFundableLiquidity#addLiquidityToJob function is called/// @param _job The address of the job to which liquidity will be added/// @param _liquidity The address of the liquidity being added/// @param _provider The user that calls the function/// @param _amount The amount of liquidity being addedeventLiquidityAddition(addressindexed _job, addressindexed _liquidity, addressindexed _provider, uint256 _amount);
/// @notice Emitted when IKeep3rJobFundableLiquidity#withdrawLiquidityFromJob function is called/// @param _job The address of the job of which liquidity will be withdrawn from/// @param _liquidity The address of the liquidity being withdrawn/// @param _receiver The receiver of the liquidity tokens/// @param _amount The amount of liquidity being withdrawn from the jobeventLiquidityWithdrawal(addressindexed _job, addressindexed _liquidity, addressindexed _receiver, uint256 _amount);
/// @notice Emitted when Keep3rJobFundableLiquidity#addLiquidityToJob function is called/// @param _job The address of the job whose credits will be updated/// @param _rewardedAt The time at which the job was last rewarded/// @param _currentCredits The current credits of the job/// @param _periodCredits The credits of the job for the current periodeventLiquidityCreditsReward(addressindexed _job, uint256 _rewardedAt, uint256 _currentCredits, uint256 _periodCredits);
/// @notice Emitted when Keep3rJobFundableLiquidity#forceLiquidityCreditsToJob function is called/// @param _job The address of the job whose credits will be updated/// @param _rewardedAt The time at which the job was last rewarded/// @param _currentCredits The current credits of the jobeventLiquidityCreditsForced(addressindexed _job, uint256 _rewardedAt, uint256 _currentCredits);
// Errors/// @notice Throws when the liquidity being approved has already been approvederrorLiquidityPairApproved();
/// @notice Throws when the liquidity being removed has not been approvederrorLiquidityPairUnexistent();
/// @notice Throws when trying to add liquidity to an unapproved poolerrorLiquidityPairUnapproved();
/// @notice Throws when the job doesn't have the requested liquidityerrorJobLiquidityUnexistent();
/// @notice Throws when trying to remove more liquidity than the job haserrorJobLiquidityInsufficient();
/// @notice Throws when trying to add less liquidity than the minimum liquidity requirederrorJobLiquidityLessThanMin();
// Structs/// @notice Stores the tick information of the different liquidity pairsstructTickCache {
int56 current; // Tracks the current tickint56 difference; // Stores the difference between the current tick and the last tickuint256 period; // Stores the period at which the last observation was made
}
// Variables/// @notice Lists liquidity pairs/// @return _list An array of addresses with all the approved liquidity pairsfunctionapprovedLiquidities() externalviewreturns (address[] memory _list);
/// @notice Amount of liquidity in a specified job/// @param _job The address of the job being checked/// @param _liquidity The address of the liquidity we are checking/// @return _amount Amount of liquidity in the specified jobfunctionliquidityAmount(address _job, address _liquidity) externalviewreturns (uint256 _amount);
/// @notice Last time the job was rewarded liquidity credits/// @param _job The address of the job being checked/// @return _timestamp Timestamp of the last time the job was rewarded liquidity creditsfunctionrewardedAt(address _job) externalviewreturns (uint256 _timestamp);
/// @notice Last time the job was worked/// @param _job The address of the job being checked/// @return _timestamp Timestamp of the last time the job was workedfunctionworkedAt(address _job) externalviewreturns (uint256 _timestamp);
// Methods/// @notice Returns the liquidity credits of a given job/// @param _job The address of the job of which we want to know the liquidity credits/// @return _amount The liquidity credits of a given jobfunctionjobLiquidityCredits(address _job) externalviewreturns (uint256 _amount);
/// @notice Returns the credits of a given job for the current period/// @param _job The address of the job of which we want to know the period credits/// @return _amount The credits the given job has at the current periodfunctionjobPeriodCredits(address _job) externalviewreturns (uint256 _amount);
/// @notice Calculates the total credits of a given job/// @param _job The address of the job of which we want to know the total credits/// @return _amount The total credits of the given jobfunctiontotalJobCredits(address _job) externalviewreturns (uint256 _amount);
/// @notice Calculates how many credits should be rewarded periodically for a given liquidity amount/// @dev _periodCredits = underlying KP3Rs for given liquidity amount * rewardPeriod / inflationPeriod/// @param _liquidity The address of the liquidity to provide/// @param _amount The amount of liquidity to provide/// @return _periodCredits The amount of KP3R periodically minted for the given liquidityfunctionquoteLiquidity(address _liquidity, uint256 _amount) externalviewreturns (uint256 _periodCredits);
/// @notice Observes the current state of the liquidity pair being observed and updates TickCache with the information/// @param _liquidity The address of the liquidity pair being observed/// @return _tickCache The updated TickCachefunctionobserveLiquidity(address _liquidity) externalviewreturns (TickCache memory _tickCache);
/// @notice Gifts liquidity credits to the specified job/// @param _job The address of the job being credited/// @param _amount The amount of liquidity credits to giftfunctionforceLiquidityCreditsToJob(address _job, uint256 _amount) external;
/// @notice Approve a liquidity pair for being accepted in future/// @param _liquidity The address of the liquidity acceptedfunctionapproveLiquidity(address _liquidity) external;
/// @notice Revoke a liquidity pair from being accepted in future/// @param _liquidity The liquidity no longer acceptedfunctionrevokeLiquidity(address _liquidity) external;
/// @notice Allows anyone to fund a job with liquidity/// @param _job The address of the job to assign liquidity to/// @param _liquidity The liquidity being added/// @param _amount The amount of liquidity tokens to addfunctionaddLiquidityToJob(address _job,
address _liquidity,
uint256 _amount
) external;
/// @notice Unbond liquidity for a job/// @dev Can only be called by the job's owner/// @param _job The address of the job being unbonded from/// @param _liquidity The liquidity being unbonded/// @param _amount The amount of liquidity being removedfunctionunbondLiquidityFromJob(address _job,
address _liquidity,
uint256 _amount
) external;
/// @notice Withdraw liquidity from a job/// @param _job The address of the job being withdrawn from/// @param _liquidity The liquidity being withdrawn/// @param _receiver The address that will receive the withdrawn liquidityfunctionwithdrawLiquidityFromJob(address _job,
address _liquidity,
address _receiver
) external;
}
/// @title Keep3rJobManager contract/// @notice Handles the addition and withdrawal of credits from a jobinterfaceIKeep3rJobManager{
// Events/// @notice Emitted when Keep3rJobManager#addJob is called/// @param _job The address of the job to add/// @param _jobOwner The job's ownereventJobAddition(addressindexed _job, addressindexed _jobOwner);
// Errors/// @notice Throws when trying to add a job that has already been addederrorJobAlreadyAdded();
/// @notice Throws when the address that is trying to register as a keeper is already a keepererrorAlreadyAKeeper();
// Methods/// @notice Allows any caller to add a new job/// @param _job Address of the contract for which work should be performedfunctionaddJob(address _job) external;
}
/// @title Keep3rJobWorkable contract/// @notice Handles the mechanisms jobs can pay keepers with along with the restrictions jobs can put on keepers before they can work on jobsinterfaceIKeep3rJobWorkable{
// Events/// @notice Emitted when a keeper is validated before a job/// @param _gasLeft The amount of gas that the transaction has left at the moment of keeper validationeventKeeperValidation(uint256 _gasLeft);
/// @notice Emitted when a keeper works a job/// @param _credit The address of the asset in which the keeper is paid/// @param _job The address of the job the keeper has worked/// @param _keeper The address of the keeper that has worked the job/// @param _payment The amount that has been paid out to the keeper in exchange for working the job/// @param _gasLeft The amount of gas that the transaction has left at the moment of paymenteventKeeperWork(addressindexed _credit, addressindexed _job, addressindexed _keeper, uint256 _payment, uint256 _gasLeft);
// Errors/// @notice Throws if the address claiming to be a job is not in the list of approved jobserrorJobUnapproved();
/// @notice Throws if the amount of funds in the job is less than the payment that must be paid to the keeper that works that joberrorInsufficientFunds();
// Methods/// @notice Confirms if the current keeper is registered/// @dev Can be used for general (non critical) functions/// @param _keeper The keeper being investigated/// @return _isKeeper Whether the address passed as a parameter is a keeper or notfunctionisKeeper(address _keeper) externalreturns (bool _isKeeper);
/// @notice Confirms if the current keeper is registered and has a minimum bond of any asset./// @dev Should be used for protected functions/// @param _keeper The keeper to check/// @param _bond The bond token being evaluated/// @param _minBond The minimum amount of bonded tokens/// @param _earned The minimum funds earned in the keepers lifetime/// @param _age The minimum keeper age required/// @return _isBondedKeeper Whether the `_keeper` meets the given requirementsfunctionisBondedKeeper(address _keeper,
address _bond,
uint256 _minBond,
uint256 _earned,
uint256 _age
) externalreturns (bool _isBondedKeeper);
/// @notice Implemented by jobs to show that a keeper performed work/// @dev Automatically calculates the payment for the keeper and pays the keeper with bonded KP3R/// @param _keeper Address of the keeper that performed the workfunctionworked(address _keeper) external;
/// @notice Implemented by jobs to show that a keeper performed work/// @dev Pays the keeper that performs the work with KP3R/// @param _keeper Address of the keeper that performed the work/// @param _payment The reward that should be allocated for the jobfunctionbondedPayment(address _keeper, uint256 _payment) external;
/// @notice Implemented by jobs to show that a keeper performed work/// @dev Pays the keeper that performs the work with a specific token/// @param _token The asset being awarded to the keeper/// @param _keeper Address of the keeper that performed the work/// @param _amount The reward that should be allocatedfunctiondirectTokenPayment(address _token,
address _keeper,
uint256 _amount
) external;
}
/// @title Keep3rJobOwnership contract/// @notice Handles the ownership of the jobsinterfaceIKeep3rJobOwnership{
// Events/// @notice Emitted when Keep3rJobOwnership#changeJobOwnership is called/// @param _job The address of the job proposed to have a change of owner/// @param _owner The current owner of the job/// @param _pendingOwner The new address proposed to be the owner of the jobeventJobOwnershipChange(addressindexed _job, addressindexed _owner, addressindexed _pendingOwner);
/// @notice Emitted when Keep3rJobOwnership#JobOwnershipAssent is called/// @param _job The address of the job which the proposed owner will now own/// @param _previousOwner The previous owner of the job/// @param _newOwner The new owner of the jobeventJobOwnershipAssent(addressindexed _job, addressindexed _previousOwner, addressindexed _newOwner);
// Errors/// @notice Throws when the caller of the function is not the job ownererrorOnlyJobOwner();
/// @notice Throws when the caller of the function is not the pending job ownererrorOnlyPendingJobOwner();
// Variables/// @notice Maps the job to the owner of the job/// @param _job The address of the job/// @return _owner The address of the owner of the jobfunctionjobOwner(address _job) externalviewreturns (address _owner);
/// @notice Maps the job to its pending owner/// @param _job The address of the job/// @return _pendingOwner The address of the pending owner of the jobfunctionjobPendingOwner(address _job) externalviewreturns (address _pendingOwner);
// Methods/// @notice Proposes a new address to be the owner of the job/// @param _job The address of the job/// @param _newOwner The address of the proposed new ownerfunctionchangeJobOwnership(address _job, address _newOwner) external;
/// @notice The proposed address accepts to be the owner of the job/// @param _job The address of the jobfunctionacceptJobOwnership(address _job) external;
}
/// @title Keep3rJobMigration contract/// @notice Handles the migration process of jobs to different addressesinterfaceIKeep3rJobMigration{
// Events/// @notice Emitted when Keep3rJobMigration#migrateJob function is called/// @param _fromJob The address of the job that requests to migrate/// @param _toJob The address at which the job requests to migrateeventJobMigrationRequested(addressindexed _fromJob, address _toJob);
/// @notice Emitted when Keep3rJobMigration#acceptJobMigration function is called/// @param _fromJob The address of the job that requested to migrate/// @param _toJob The address at which the job had requested to migrateeventJobMigrationSuccessful(address _fromJob, addressindexed _toJob);
// Errors/// @notice Throws when the address of the job that requests to migrate wants to migrate to its same addresserrorJobMigrationImpossible();
/// @notice Throws when the _toJob address differs from the address being tracked in the pendingJobMigrations mappingerrorJobMigrationUnavailable();
/// @notice Throws when cooldown between migrations has not yet passederrorJobMigrationLocked();
// Variables/// @notice Maps the jobs that have requested a migration to the address they have requested to migrate to/// @return _toJob The address to which the job has requested to migrate tofunctionpendingJobMigrations(address _fromJob) externalviewreturns (address _toJob);
// Methods/// @notice Initializes the migration process for a job by adding the request to the pendingJobMigrations mapping/// @param _fromJob The address of the job that is requesting to migrate/// @param _toJob The address at which the job is requesting to migratefunctionmigrateJob(address _fromJob, address _toJob) external;
/// @notice Completes the migration process for a job/// @dev Unbond/withdraw process doesn't get migrated/// @param _fromJob The address of the job that requested to migrate/// @param _toJob The address to which the job wants to migrate tofunctionacceptJobMigration(address _fromJob, address _toJob) external;
}
/// @title Keep3rJobDisputable contract/// @notice Handles the actions that can be taken on a disputed jobinterfaceIKeep3rJobDisputableisIKeep3rJobFundableCredits, IKeep3rJobFundableLiquidity{
// Events/// @notice Emitted when Keep3rJobDisputable#slashTokenFromJob is called/// @param _job The address of the job from which the token will be slashed/// @param _token The address of the token being slashed/// @param _slasher The user that slashes the token/// @param _amount The amount of the token being slashedeventJobSlashToken(addressindexed _job, address _token, addressindexed _slasher, uint256 _amount);
/// @notice Emitted when Keep3rJobDisputable#slashLiquidityFromJob is called/// @param _job The address of the job from which the liquidity will be slashed/// @param _liquidity The address of the liquidity being slashed/// @param _slasher The user that slashes the liquidity/// @param _amount The amount of the liquidity being slashedeventJobSlashLiquidity(addressindexed _job, address _liquidity, addressindexed _slasher, uint256 _amount);
// Errors/// @notice Throws when the token trying to be slashed doesn't existerrorJobTokenUnexistent();
/// @notice Throws when someone tries to slash more tokens than the job haserrorJobTokenInsufficient();
// Methods/// @notice Allows governance or slasher to slash a job specific token/// @param _job The address of the job from which the token will be slashed/// @param _token The address of the token that will be slashed/// @param _amount The amount of the token that will be slashedfunctionslashTokenFromJob(address _job,
address _token,
uint256 _amount
) external;
/// @notice Allows governance or a slasher to slash liquidity from a job/// @param _job The address being slashed/// @param _liquidity The address of the liquidity that will be slashed/// @param _amount The amount of liquidity that will be slashedfunctionslashLiquidityFromJob(address _job,
address _liquidity,
uint256 _amount
) external;
}
// solhint-disable-next-line no-empty-blocksinterfaceIKeep3rJobsisIKeep3rJobOwnership, IKeep3rJobDisputable, IKeep3rJobMigration, IKeep3rJobManager, IKeep3rJobWorkable{
}
Código Fuente del Contrato
Archivo 15 de 39: IKeep3rKeepers.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;/// @title Keep3rKeeperFundable contract/// @notice Handles the actions required to become a keeperinterfaceIKeep3rKeeperFundable{
// Events/// @notice Emitted when Keep3rKeeperFundable#activate is called/// @param _keeper The keeper that has been activated/// @param _bond The asset the keeper has bonded/// @param _amount The amount of the asset the keeper has bondedeventActivation(addressindexed _keeper, addressindexed _bond, uint256 _amount);
/// @notice Emitted when Keep3rKeeperFundable#withdraw is called/// @param _keeper The caller of Keep3rKeeperFundable#withdraw function/// @param _bond The asset to withdraw from the bonding pool/// @param _amount The amount of funds withdrawneventWithdrawal(addressindexed _keeper, addressindexed _bond, uint256 _amount);
// Errors/// @notice Throws when the address that is trying to register as a job is already a joberrorAlreadyAJob();
// Methods/// @notice Beginning of the bonding process/// @param _bonding The asset being bonded/// @param _amount The amount of bonding asset being bondedfunctionbond(address _bonding, uint256 _amount) external;
/// @notice Beginning of the unbonding process/// @param _bonding The asset being unbonded/// @param _amount Allows for partial unbondingfunctionunbond(address _bonding, uint256 _amount) external;
/// @notice End of the bonding process after bonding time has passed/// @param _bonding The asset being activated as bond collateralfunctionactivate(address _bonding) external;
/// @notice Withdraw funds after unbonding has finished/// @param _bonding The asset to withdraw from the bonding poolfunctionwithdraw(address _bonding) external;
}
/// @title Keep3rKeeperDisputable contract/// @notice Handles the actions that can be taken on a disputed keeperinterfaceIKeep3rKeeperDisputable{
// Events/// @notice Emitted when Keep3rKeeperDisputable#slash is called/// @param _keeper The address of the slashed keeper/// @param _slasher The user that called Keep3rKeeperDisputable#slash/// @param _amount The amount of credits slashed from the keepereventKeeperSlash(addressindexed _keeper, addressindexed _slasher, uint256 _amount);
/// @notice Emitted when Keep3rKeeperDisputable#revoke is called/// @param _keeper The address of the revoked keeper/// @param _slasher The user that called Keep3rKeeperDisputable#revokeeventKeeperRevoke(addressindexed _keeper, addressindexed _slasher);
// Methods/// @notice Allows governance to slash a keeper based on a dispute/// @param _keeper The address being slashed/// @param _bonded The asset being slashed/// @param _bondAmount The bonded amount being slashed/// @param _unbondAmount The pending unbond amount being slashedfunctionslash(address _keeper,
address _bonded,
uint256 _bondAmount,
uint256 _unbondAmount
) external;
/// @notice Blacklists a keeper from participating in the network/// @param _keeper The address being slashedfunctionrevoke(address _keeper) external;
}
// solhint-disable-next-line no-empty-blocks/// @title Keep3rKeepers contractinterfaceIKeep3rKeepersisIKeep3rKeeperDisputable{
}
Código Fuente del Contrato
Archivo 16 de 39: IKeep3rParameters.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;import'./IBaseErrors.sol';
/// @title Keep3rParameters contract/// @notice Handles and sets all the required parameters for Keep3rinterfaceIKeep3rParametersisIBaseErrors{
// Events/// @notice Emitted when the Keep3rHelper address is changed/// @param _keep3rHelper The address of Keep3rHelper's contracteventKeep3rHelperChange(address _keep3rHelper);
/// @notice Emitted when the Keep3rV1 address is changed/// @param _keep3rV1 The address of Keep3rV1's contracteventKeep3rV1Change(address _keep3rV1);
/// @notice Emitted when the Keep3rV1Proxy address is changed/// @param _keep3rV1Proxy The address of Keep3rV1Proxy's contracteventKeep3rV1ProxyChange(address _keep3rV1Proxy);
/// @notice Emitted when the KP3R-WETH pool address is changed/// @param _kp3rWethPool The address of the KP3R-WETH pooleventKp3rWethPoolChange(address _kp3rWethPool);
/// @notice Emitted when bondTime is changed/// @param _bondTime The new bondTimeeventBondTimeChange(uint256 _bondTime);
/// @notice Emitted when _liquidityMinimum is changed/// @param _liquidityMinimum The new _liquidityMinimumeventLiquidityMinimumChange(uint256 _liquidityMinimum);
/// @notice Emitted when _unbondTime is changed/// @param _unbondTime The new _unbondTimeeventUnbondTimeChange(uint256 _unbondTime);
/// @notice Emitted when _rewardPeriodTime is changed/// @param _rewardPeriodTime The new _rewardPeriodTimeeventRewardPeriodTimeChange(uint256 _rewardPeriodTime);
/// @notice Emitted when the inflationPeriod is changed/// @param _inflationPeriod The new inflationPeriodeventInflationPeriodChange(uint256 _inflationPeriod);
/// @notice Emitted when the fee is changed/// @param _fee The new token credits feeeventFeeChange(uint256 _fee);
// Variables/// @notice Address of Keep3rHelper's contract/// @return _keep3rHelper The address of Keep3rHelper's contractfunctionkeep3rHelper() externalviewreturns (address _keep3rHelper);
/// @notice Address of Keep3rV1's contract/// @return _keep3rV1 The address of Keep3rV1's contractfunctionkeep3rV1() externalviewreturns (address _keep3rV1);
/// @notice Address of Keep3rV1Proxy's contract/// @return _keep3rV1Proxy The address of Keep3rV1Proxy's contractfunctionkeep3rV1Proxy() externalviewreturns (address _keep3rV1Proxy);
/// @notice Address of the KP3R-WETH pool/// @return _kp3rWethPool The address of KP3R-WETH poolfunctionkp3rWethPool() externalviewreturns (address _kp3rWethPool);
/// @notice The amount of time required to pass after a keeper has bonded assets for it to be able to activate/// @return _days The required bondTime in daysfunctionbondTime() externalviewreturns (uint256 _days);
/// @notice The amount of time required to pass before a keeper can unbond what he has bonded/// @return _days The required unbondTime in daysfunctionunbondTime() externalviewreturns (uint256 _days);
/// @notice The minimum amount of liquidity required to fund a job per liquidity/// @return _amount The minimum amount of liquidity in KP3RfunctionliquidityMinimum() externalviewreturns (uint256 _amount);
/// @notice The amount of time between each scheduled credits reward given to a job/// @return _days The reward period in daysfunctionrewardPeriodTime() externalviewreturns (uint256 _days);
/// @notice The inflation period is the denominator used to regulate the emission of KP3R/// @return _period The denominator used to regulate the emission of KP3RfunctioninflationPeriod() externalviewreturns (uint256 _period);
/// @notice The fee to be sent to governance when a user adds liquidity to a job/// @return _amount The fee amount to be sent to governance when a user adds liquidity to a jobfunctionfee() externalviewreturns (uint256 _amount);
// Errors/// @notice Throws if the reward period is less than the minimum reward period timeerrorMinRewardPeriod();
/// @notice Throws if either a job or a keeper is disputederrorDisputed();
/// @notice Throws if there are no bonded assetserrorBondsUnexistent();
/// @notice Throws if the time required to bond an asset has not passed yeterrorBondsLocked();
/// @notice Throws if there are no bonds to withdrawerrorUnbondsUnexistent();
/// @notice Throws if the time required to withdraw the bonds has not passed yeterrorUnbondsLocked();
// Methods/// @notice Sets the Keep3rHelper address/// @param _keep3rHelper The Keep3rHelper addressfunctionsetKeep3rHelper(address _keep3rHelper) external;
/// @notice Sets the Keep3rV1 address/// @param _keep3rV1 The Keep3rV1 addressfunctionsetKeep3rV1(address _keep3rV1) external;
/// @notice Sets the Keep3rV1Proxy address/// @param _keep3rV1Proxy The Keep3rV1Proxy addressfunctionsetKeep3rV1Proxy(address _keep3rV1Proxy) external;
/// @notice Sets the KP3R-WETH pool address/// @param _kp3rWethPool The KP3R-WETH pool addressfunctionsetKp3rWethPool(address _kp3rWethPool) external;
/// @notice Sets the bond time required to activate as a keeper/// @param _bond The new bond timefunctionsetBondTime(uint256 _bond) external;
/// @notice Sets the unbond time required unbond what has been bonded/// @param _unbond The new unbond timefunctionsetUnbondTime(uint256 _unbond) external;
/// @notice Sets the minimum amount of liquidity required to fund a job/// @param _liquidityMinimum The new minimum amount of liquidityfunctionsetLiquidityMinimum(uint256 _liquidityMinimum) external;
/// @notice Sets the time required to pass between rewards for jobs/// @param _rewardPeriodTime The new amount of time required to pass between rewardsfunctionsetRewardPeriodTime(uint256 _rewardPeriodTime) external;
/// @notice Sets the new inflation period/// @param _inflationPeriod The new inflation periodfunctionsetInflationPeriod(uint256 _inflationPeriod) external;
/// @notice Sets the new fee/// @param _fee The new feefunctionsetFee(uint256 _fee) external;
}
Código Fuente del Contrato
Archivo 17 de 39: IKeep3rRoles.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;/// @title Keep3rRoles contract/// @notice Manages the Keep3r specific rolesinterfaceIKeep3rRoles{
// Events/// @notice Emitted when a slasher is added/// @param _slasher Address of the added slashereventSlasherAdded(address _slasher);
/// @notice Emitted when a slasher is removed/// @param _slasher Address of the removed slashereventSlasherRemoved(address _slasher);
/// @notice Emitted when a disputer is added/// @param _disputer Address of the added disputereventDisputerAdded(address _disputer);
/// @notice Emitted when a disputer is removed/// @param _disputer Address of the removed disputereventDisputerRemoved(address _disputer);
// Variables/// @notice Tracks whether the address is a slasher or not/// @param _slasher Address being checked as a slasher/// @return _isSlasher Whether the address is a slasher or notfunctionslashers(address _slasher) externalviewreturns (bool _isSlasher);
/// @notice Tracks whether the address is a disputer or not/// @param _disputer Address being checked as a disputer/// @return _isDisputer Whether the address is a disputer or notfunctiondisputers(address _disputer) externalviewreturns (bool _isDisputer);
// Errors/// @notice Throws if the address is already a registered slashererrorSlasherExistent();
/// @notice Throws if caller is not a registered slashererrorSlasherUnexistent();
/// @notice Throws if the address is already a registered disputererrorDisputerExistent();
/// @notice Throws if caller is not a registered disputererrorDisputerUnexistent();
/// @notice Throws if the msg.sender is not a slasher or is not a part of governanceerrorOnlySlasher();
/// @notice Throws if the msg.sender is not a disputer or is not a part of governanceerrorOnlyDisputer();
// Methods/// @notice Registers a slasher by updating the slashers mappingfunctionaddSlasher(address _slasher) external;
/// @notice Removes a slasher by updating the slashers mappingfunctionremoveSlasher(address _slasher) external;
/// @notice Registers a disputer by updating the disputers mappingfunctionaddDisputer(address _disputer) external;
/// @notice Removes a disputer by updating the disputers mappingfunctionremoveDisputer(address _disputer) external;
}
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;import'@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';
/// @title Pair Manager interface/// @notice Generic interface for Keep3r liquidity pools (kLP)interfaceIPairManagerisIERC20Metadata{
/// @notice Address of the factory from which the pair manager was created/// @return _factory The address of the PairManager Factoryfunctionfactory() externalviewreturns (address _factory);
/// @notice Address of the pool from which the Keep3r pair manager will interact with/// @return _pool The address of the poolfunctionpool() externalviewreturns (address _pool);
/// @notice Token0 of the pool/// @return _token0 The address of token0functiontoken0() externalviewreturns (address _token0);
/// @notice Token1 of the pool/// @return _token1 The address of token1functiontoken1() externalviewreturns (address _token1);
}
// SPDX-License-Identifier: MITpragmasolidity >=0.8.4 <0.9.0;import'../../interfaces/peripherals/IKeep3rRoles.sol';
import'@openzeppelin/contracts/utils/structs/EnumerableSet.sol';
import'./Governable.sol';
contractKeep3rRolesisIKeep3rRoles, Governable{
/// @inheritdoc IKeep3rRolesmapping(address=>bool) publicoverride slashers;
/// @inheritdoc IKeep3rRolesmapping(address=>bool) publicoverride disputers;
constructor(address _governance) Governable(_governance) {}
/// @inheritdoc IKeep3rRolesfunctionaddSlasher(address _slasher) externaloverrideonlyGovernance{
if (slashers[_slasher]) revert SlasherExistent();
slashers[_slasher] =true;
emit SlasherAdded(_slasher);
}
/// @inheritdoc IKeep3rRolesfunctionremoveSlasher(address _slasher) externaloverrideonlyGovernance{
if (!slashers[_slasher]) revert SlasherUnexistent();
delete slashers[_slasher];
emit SlasherRemoved(_slasher);
}
/// @inheritdoc IKeep3rRolesfunctionaddDisputer(address _disputer) externaloverrideonlyGovernance{
if (disputers[_disputer]) revert DisputerExistent();
disputers[_disputer] =true;
emit DisputerAdded(_disputer);
}
/// @inheritdoc IKeep3rRolesfunctionremoveDisputer(address _disputer) externaloverrideonlyGovernance{
if (!disputers[_disputer]) revert DisputerUnexistent();
delete disputers[_disputer];
emit DisputerRemoved(_disputer);
}
/// @notice Functions with this modifier can only be called by either a slasher or governancemodifieronlySlasher{
if (!slashers[msg.sender]) revert OnlySlasher();
_;
}
/// @notice Functions with this modifier can only be called by either a disputer or governancemodifieronlyDisputer{
if (!disputers[msg.sender]) revert OnlyDisputer();
_;
}
}
Código Fuente del Contrato
Archivo 37 de 39: Math.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @dev Standard math utilities missing in the Solidity language.
*/libraryMath{
/**
* @dev Returns the largest of two numbers.
*/functionmax(uint256 a, uint256 b) internalpurereturns (uint256) {
return a >= b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/functionmin(uint256 a, uint256 b) internalpurereturns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/functionaverage(uint256 a, uint256 b) internalpurereturns (uint256) {
// (a + b) / 2 can overflow.return (a & b) + (a ^ b) /2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/functionceilDiv(uint256 a, uint256 b) internalpurereturns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.return a / b + (a % b ==0 ? 0 : 1);
}
}
Código Fuente del Contrato
Archivo 38 de 39: ReentrancyGuard.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/abstractcontractReentrancyGuard{
// Booleans are more expensive than uint256 or any type that takes up a full// word because each write operation emits an extra SLOAD to first read the// slot's contents, replace the bits taken up by the boolean, and then write// back. This is the compiler's defense against contract upgrades and// pointer aliasing, and it cannot be disabled.// The values being non-zero value makes deployment a bit more expensive,// but in exchange the refund on every call to nonReentrant will be lower in// amount. Since refunds are capped to a percentage of the total// transaction's gas, it is best to keep them low in cases like this one, to// increase the likelihood of the full refund coming into effect.uint256privateconstant _NOT_ENTERED =1;
uint256privateconstant _ENTERED =2;
uint256private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/modifiernonReentrant() {
// On the first call to nonReentrant, _notEntered will be truerequire(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
Código Fuente del Contrato
Archivo 39 de 39: SafeERC20.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"../IERC20.sol";
import"../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/librarySafeERC20{
usingAddressforaddress;
functionsafeTransfer(
IERC20 token,
address to,
uint256 value
) internal{
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
functionsafeTransferFrom(
IERC20 token,
addressfrom,
address to,
uint256 value
) internal{
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/functionsafeApprove(
IERC20 token,
address spender,
uint256 value
) internal{
// safeApprove should only be called when setting an initial allowance,// or when resetting it to zero. To increase and decrease it, use// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'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));
}
functionsafeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal{
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
functionsafeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal{
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/function_callOptionalReturn(IERC20 token, bytesmemory data) private{
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that// the target address contains contract code and also asserts for success in the low-level call.bytesmemory returndata =address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length>0) {
// Return data is optionalrequire(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}