Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"@openzeppelin/contracts/security/Pausable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
"
},
"@openzeppelin/contracts/token/ERC20/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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);
}
"
},
"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^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.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @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.
*/
function safeApprove(
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));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
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, bytes memory 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.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
"
},
"@openzeppelin/contracts/utils/Address.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @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
* ====
*/
function isContract(address account) internal view returns (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].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @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._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
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._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
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._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @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._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
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._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
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._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @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._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
"
},
"@openzeppelin/contracts/utils/Context.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @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 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 Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
"
},
"@openzeppelin/contracts/utils/math/Math.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (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.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a / b + (a % b == 0 ? 0 : 1);
}
}
"
},
"@openzeppelin/contracts/utils/math/SafeCast.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)
pragma solidity ^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 SafeCast {
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @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 <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(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 <= type(uint64).max, "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 <= type(uint32).max, "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 <= type(uint16).max, "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 <= type(uint8).max, "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 >= type(int128).min && value <= type(int128).max, "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 >= type(int64).min && value <= type(int64).max, "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 >= type(int32).min && value <= type(int32).max, "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 >= type(int16).min && value <= type(int16).max, "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 >= type(int8).min && value <= type(int8).max, "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) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}
"
},
"contracts/beacon/BeaconRoots.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
/**
* @title Library to retrieve beacon block roots.
* @author Origin Protocol Inc
*/
library BeaconRoots {
/// @notice The address of beacon block roots oracle
/// See https://eips.ethereum.org/EIPS/eip-4788
address internal constant BEACON_ROOTS_ADDRESS =
0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02;
/// @notice Returns the beacon block root for the previous block.
/// This comes from the Beacon Roots contract defined in EIP-4788.
/// This will revert if the block is more than 8,191 blocks old as
/// that is the size of the beacon root's ring buffer.
/// @param timestamp The timestamp of the block for which to get the parent root.
/// @return parentRoot The parent block root for the given timestamp.
function parentBlockRoot(uint64 timestamp)
internal
view
returns (bytes32 parentRoot)
{
// Call the Beacon Roots contract to get the parent block root.
// This does not have a function signature, so we use a staticcall.
(bool success, bytes memory result) = BEACON_ROOTS_ADDRESS.staticcall(
abi.encode(timestamp)
);
require(success && result.length > 0, "Invalid beacon timestamp");
parentRoot = abi.decode(result, (bytes32));
}
}
"
},
"contracts/beacon/PartialWithdrawal.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
/**
* @title Library to request full or partial withdrawals from validators on the beacon chain.
* @author Origin Protocol Inc
*/
library PartialWithdrawal {
/// @notice The address where the withdrawal request is sent to
/// See https://eips.ethereum.org/EIPS/eip-7002
address internal constant WITHDRAWAL_REQUEST_ADDRESS =
0x00000961Ef480Eb55e80D19ad83579A64c007002;
/// @notice Requests a partial withdrawal for a given validator public key and amount.
/// @param validatorPubKey The public key of the validator to withdraw from
/// @param amount The amount of ETH to withdraw
function request(bytes calldata validatorPubKey, uint64 amount)
internal
returns (uint256 fee_)
{
require(validatorPubKey.length == 48, "Invalid validator byte length");
fee_ = fee();
// Call the Withdrawal Request contract with the validator public key
// and amount to be withdrawn packed together
// This is a general purpose EL to CL request:
// https://eips.ethereum.org/EIPS/eip-7685
(bool success, ) = WITHDRAWAL_REQUEST_ADDRESS.call{ value: fee_ }(
abi.encodePacked(validatorPubKey, amount)
);
require(success, "Withdrawal request failed");
}
/// @notice Gets fee for withdrawal requests contract on Beacon chain
function fee() internal view returns (uint256) {
// Get fee from the withdrawal request contract
(bool success, bytes memory result) = WITHDRAWAL_REQUEST_ADDRESS
.staticcall("");
require(success && result.length > 0, "Failed to get fee");
return abi.decode(result, (uint256));
}
}
"
},
"contracts/governance/Governable.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
/**
* @title Base for contracts that are managed by the Origin Protocol's Governor.
* @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change
* from owner to governor and renounce methods removed. Does not use
* Context.sol like Ownable.sol does for simplification.
* @author Origin Protocol Inc
*/
abstract contract Governable {
// Storage position of the owner and pendingOwner of the contract
// keccak256("OUSD.governor");
bytes32 private constant governorPosition =
0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;
// keccak256("OUSD.pending.governor");
bytes32 private constant pendingGovernorPosition =
0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;
// keccak256("OUSD.reentry.status");
bytes32 private constant reentryStatusPosition =
0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;
// See OpenZeppelin ReentrancyGuard implementation
uint256 constant _NOT_ENTERED = 1;
uint256 constant _ENTERED = 2;
event PendingGovernorshipTransfer(
address indexed previousGovernor,
address indexed newGovernor
);
event GovernorshipTransferred(
address indexed previousGovernor,
address indexed newGovernor
);
/**
* @notice Returns the address of the current Governor.
*/
function governor() public view returns (address) {
return _governor();
}
/**
* @dev Returns the address of the current Governor.
*/
function _governor() internal view returns (address governorOut) {
bytes32 position = governorPosition;
// solhint-disable-next-line no-inline-assembly
assembly {
governorOut := sload(position)
}
}
/**
* @dev Returns the address of the pending Governor.
*/
function _pendingGovernor()
internal
view
returns (address pendingGovernor)
{
bytes32 position = pendingGovernorPosition;
// solhint-disable-next-line no-inline-assembly
assembly {
pendingGovernor := sload(position)
}
}
/**
* @dev Throws if called by any account other than the Governor.
*/
modifier onlyGovernor() {
require(isGovernor(), "Caller is not the Governor");
_;
}
/**
* @notice Returns true if the caller is the current Governor.
*/
function isGovernor() public view returns (bool) {
return msg.sender == _governor();
}
function _setGovernor(address newGovernor) internal {
emit GovernorshipTransferred(_governor(), newGovernor);
bytes32 position = governorPosition;
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(position, newGovernor)
}
}
/**
* @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.
*/
modifier nonReentrant() {
bytes32 position = reentryStatusPosition;
uint256 _reentry_status;
// solhint-disable-next-line no-inline-assembly
assembly {
_reentry_status := sload(position)
}
// On the first call to nonReentrant, _notEntered will be true
require(_reentry_status != _ENTERED, "Reentrant call");
// Any calls to nonReentrant after this point will fail
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(position, _ENTERED)
}
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(position, _NOT_ENTERED)
}
}
function _setPendingGovernor(address newGovernor) internal {
bytes32 position = pendingGovernorPosition;
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(position, newGovernor)
}
}
/**
* @notice Transfers Governance of the contract to a new account (`newGovernor`).
* Can only be called by the current Governor. Must be claimed for this to complete
* @param _newGovernor Address of the new Governor
*/
function transferGovernance(address _newGovernor) external onlyGovernor {
_setPendingGovernor(_newGovernor);
emit PendingGovernorshipTransfer(_governor(), _newGovernor);
}
/**
* @notice Claim Governance of the contract to a new account (`newGovernor`).
* Can only be called by the new Governor.
*/
function claimGovernance() external {
require(
msg.sender == _pendingGovernor(),
"Only the pending Governor can complete the claim"
);
_changeGovernor(msg.sender);
}
/**
* @dev Change Governance of the contract to a new account (`newGovernor`).
* @param _newGovernor Address of the new Governor
*/
function _changeGovernor(address _newGovernor) internal {
require(_newGovernor != address(0), "New Governor is address(0)");
_setGovernor(_newGovernor);
}
}
"
},
"contracts/interfaces/IBasicToken.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IBasicToken {
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
"
},
"contracts/interfaces/IBeaconProofs.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
interface IBeaconProofs {
function verifyValidator(
bytes32 beaconBlockRoot,
bytes32 pubKeyHash,
bytes calldata validatorPubKeyProof,
uint40 validatorIndex,
bytes32 withdrawalCredentials
) external view;
function verifyValidatorWithdrawable(
bytes32 beaconBlockRoot,
uint40 validatorIndex,
uint64 withdrawableEpoch,
bytes calldata withdrawableEpochProof
) external view;
function verifyBalancesContainer(
bytes32 beaconBlockRoot,
bytes32 balancesContainerLeaf,
bytes calldata balancesContainerProof
) external view;
function verifyValidatorBalance(
bytes32 balancesContainerRoot,
bytes32 validatorBalanceLeaf,
bytes calldata balanceProof,
uint40 validatorIndex
) external view returns (uint256 validatorBalance);
function verifyPendingDepositsContainer(
bytes32 beaconBlockRoot,
bytes32 pendingDepositsContainerRoot,
bytes calldata proof
) external view;
function verifyPendingDeposit(
bytes32 pendingDepositsContainerRoot,
bytes32 pendingDepositRoot,
bytes calldata proof,
uint32 pendingDepositIndex
) external view;
function verifyFirstPendingDeposit(
bytes32 beaconBlockRoot,
uint64 slot,
bytes calldata firstPendingDepositSlotProof
) external view returns (bool isEmptyDepositQueue);
function merkleizePendingDeposit(
bytes32 pubKeyHash,
bytes calldata withdrawalCredentials,
uint64 amountGwei,
bytes calldata signature,
uint64 slot
) external pure returns (bytes32 root);
function merkleizeSignature(bytes calldata signature)
external
pure
returns (bytes32 root);
}
"
},
"contracts/interfaces/IDepositContract.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IDepositContract {
/// @notice A processed deposit event.
event DepositEvent(
bytes pubkey,
bytes withdrawal_credentials,
bytes amount,
bytes signature,
bytes index
);
/// @notice Submit a Phase 0 DepositData object.
/// @param pubkey A BLS12-381 public key.
/// @param withdrawal_credentials Commitment to a public key for withdrawals.
/// @param signature A BLS12-381 signature.
/// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object.
/// Used as a protection against malformed input.
function deposit(
bytes calldata pubkey,
bytes calldata withdrawal_credentials,
bytes calldata signature,
bytes32 deposit_data_root
) external payable;
/// @notice Query the current deposit root hash.
/// @return The deposit root hash.
function get_deposit_root() external view returns (bytes32);
/// @notice Query the current deposit count.
/// @return The deposit count encoded as a little endian 64-bit number.
function get_deposit_count() external view returns (bytes memory);
}
"
},
"contracts/interfaces/ISSVNetwork.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
struct Cluster {
uint32 validatorCount;
uint64 networkFeeIndex;
uint64 index;
bool active;
uint256 balance;
}
interface ISSVNetwork {
/**********/
/* Errors */
/**********/
error CallerNotOwner(); // 0x5cd83192
error CallerNotWhitelisted(); // 0x8c6e5d71
error FeeTooLow(); // 0x732f9413
error FeeExceedsIncreaseLimit(); // 0x958065d9
error NoFeeDeclared(); // 0x1d226c30
error ApprovalNotWithinTimeframe(); // 0x97e4b518
error OperatorDoesNotExist(); // 0x961e3e8c
error InsufficientBalance(); // 0xf4d678b8
error ValidatorDoesNotExist(); // 0xe51315d2
error ClusterNotLiquidatable(); // 0x60300a8d
error InvalidPublicKeyLength(); // 0x637297a4
error InvalidOperatorIdsLength(); // 0x38186224
error ClusterAlreadyEnabled(); // 0x3babafd2
error ClusterIsLiquidated(); // 0x95a0cf33
error ClusterDoesNotExists(); // 0x185e2b16
error IncorrectClusterState(); // 0x12e04c87
error UnsortedOperatorsList(); // 0xdd020e25
error NewBlockPeriodIsBelowMinimum(); // 0x6e6c9cac
error ExceedValidatorLimit(); // 0x6df5ab76
error TokenTransferFailed(); // 0x045c4b02
error SameFeeChangeNotAllowed(); // 0xc81272f8
error FeeIncreaseNotAllowed(); // 0x410a2b6c
error NotAuthorized(); // 0xea8e4eb5
error OperatorsListNotUnique(); // 0xa5a1ff5d
error OperatorAlreadyExists(); // 0x289c9494
error TargetModuleDoesNotExist(); // 0x8f9195fb
error MaxValueExceeded(); // 0x91aa3017
error FeeTooHigh(); // 0xcd4e6167
error PublicKeysSharesLengthMismatch(); // 0x9ad467b8
error IncorrectValidatorStateWithData(bytes publicKey); // 0x89307938
error ValidatorAlreadyExistsWithData(bytes publicKey); // 0x388e7999
error EmptyPublicKeysList(); // df83e679
// legacy errors
error ValidatorAlreadyExists(); // 0x8d09a73e
error IncorrectValidatorState(); // 0x2feda3c1
event AdminChanged(address previousAdmin, address newAdmin);
event BeaconUpgraded(address indexed beacon);
event ClusterDeposited(
address indexed owner,
uint64[] operatorIds,
uint256 value,
Cluster cluster
);
event ClusterLiquidated(
address indexed owner,
uint64[] operatorIds,
Cluster cluster
);
event ClusterReactivated(
address indexed owner,
uint64[] operatorIds,
Cluster cluster
);
event ClusterWithdrawn(
address indexed owner,
uint64[] operatorIds,
uint256 value,
Cluster cluster
);
event DeclareOperatorFeePeriodUpdated(uint64 value);
event ExecuteOperatorFeePeriodUpdated(uint64 value);
event FeeRecipientAddressUpdated(
address indexed owner,
address recipientAddress
);
event Initialized(uint8 version);
event LiquidationThresholdPeriodUpdated(uint64 value);
event MinimumLiquidationCollateralUpdated(uint256 value);
event NetworkEarningsWithdrawn(uint256 value, address recipient);
event NetworkFeeUpdated(uint256 oldFee, uint256 newFee);
event OperatorAdded(
uint64 indexed operatorId,
address indexed owner,
bytes publicKey,
uint256 fee
);
event OperatorFeeDeclarationCancelled(
address indexed owner,
uint64 indexed operatorId
);
event OperatorFeeDeclared(
address indexed owner,
uint64 indexed operatorId,
uint256 blockNumber,
uint256 fee
);
event OperatorFeeExecuted(
address indexed owner,
uint64 indexed operatorId,
uint256 blockNumber,
uint256 fee
);
event OperatorFeeIncreaseLimitUpdated(uint64 value);
event OperatorMaximumFeeUpdated(uint64 maxFee);
event OperatorRemoved(uint64 indexed operatorId);
event OperatorWhitelistUpdated(
uint64 indexed operatorId,
address whitelisted
);
event OperatorWithdrawn(
address indexed owner,
uint64 indexed operatorId,
uint256 value
);
event OwnershipTransferStarted(
address indexed previousOwner,
address indexed newOwner
);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
event Upgraded(address indexed implementation);
event ValidatorAdded(
address indexed owner,
uint64[] operatorIds,
bytes publicKey,
bytes shares,
Cluster cluster
);
event ValidatorExited(
address indexed owner,
uint64[] operatorIds,
bytes publicKey
);
event ValidatorRemoved(
address indexed owner,
uint64[] operatorIds,
bytes publicKey,
Cluster cluster
);
fallback() external;
function acceptOwnership() external;
function cancelDeclaredOperatorFee(uint64 operatorId) external;
function declareOperatorFee(uint64 operatorId, uint256 fee) external;
function deposit(
address clusterOwner,
uint64[] memory operatorIds,
uint256 amount,
Cluster memory cluster
) external;
function executeOperatorFee(uint64 operatorId) external;
function exitValidator(bytes memory publicKey, uint64[] memory operatorIds)
external;
function bulkExitValidator(
bytes[] calldata publicKeys,
uint64[] calldata operatorIds
) external;
function getVersion() external pure returns (string memory version);
function initialize(
address token_,
address ssvOperators_,
address ssvClusters_,
address ssvDAO_,
address ssvViews_,
uint64 minimumBlocksBeforeLiquidation_,
uint256 minimumLiquidationCollateral_,
uint32 validatorsPerOperatorLimit_,
uint64 declareOperatorFeePeriod_,
uint64 executeOperatorFeePeriod_,
uint64 operatorMaxFeeIncrease_
) external;
function liquidate(
address clusterOwner,
uint64[] memory operatorIds,
Cluster memory cluster
) external;
function owner() external view returns (address);
function pendingOwner() external view returns (address);
function proxiableUUID() external view returns (bytes32);
function reactivate(
uint64[] memory operatorIds,
uint256 amount,
Cluster memory cluster
) external;
function reduceOperatorFee(uint64 operatorId, uint256 fee) external;
function registerOperator(bytes memory publicKey, uint256 fee)
external
returns (uint64 id);
function registerValidator(
bytes memory publicKey,
uint64[] memory operatorIds,
bytes memory sharesData,
uint256 amount,
Cluster memory cluster
) external;
function bulkRegisterValidator(
bytes[] calldata publicKeys,
uint64[] calldata operatorIds,
bytes[] calldata sharesData,
uint256 amount,
Cluster memory cluster
) external;
function removeOperator(uint64 operatorId) external;
function removeValidator(
bytes memory publicKey,
uint64[] memory operatorIds,
Cluster memory cluster
) external;
function bulkRemoveValidator(
bytes[] calldata publicKeys,
uint64[] calldata operatorIds,
Cluster memory cluster
) external;
function renounceOwnership() external;
function setFeeRecipientAddress(address recipientAddress) external;
function setOperatorWhitelist(uint64 operatorId, address whitelisted)
external;
function transferOwnership(address newOwner) external;
function updateDeclareOperatorFeePeriod(uint64 timeInSeconds) external;
function updateExecuteOperatorFeePeriod(uint64 timeInSeconds) external;
function updateLiquidationThresholdPeriod(uint64 blocks) external;
function updateMaximumOperatorFee(uint64 maxFee) external;
function updateMinimumLiquidationCollateral(uint256 amount) external;
function updateModule(uint8 moduleId, address moduleAddress) external;
function updateNetworkFee(uint256 fee) external;
function updateOperatorFeeIncreaseLimit(uint64 percentage) external;
function upgradeTo(address newImplementation) external;
function upgradeToAndCall(address newImplementation, bytes memory data)
external
payable;
function withdraw(
uint64[] memory operatorIds,
uint256 amount,
Cluster memory cluster
) external;
function withdrawAllOperatorEarnings(uint64 operatorId) external;
function withdrawNetworkEarnings(uint256 amount) external;
function withdrawOperatorEarnings(uint64 operatorId, uint256 amount)
external;
}
"
},
"contracts/interfaces/IStrategy.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
/**
* @title Platform interface to integrate with lending platform like Compound, AAVE etc.
*/
interface IStrategy {
/**
* @dev Deposit the given asset to platform
* @param _asset asset address
* @param _amount Amount to deposit
*/
function deposit(address _asset, uint256 _amount) external;
/**
* @dev Deposit the entire balance of all supported assets in the Strategy
* to the platform
*/
function depositAll() external;
/**
* @dev Withdraw given asset from Lending platform
*/
function withdraw(
address _recipient,
address _asset,
uint256 _amount
) external;
/**
* @dev Liquidate all assets in strategy and return them to Vault.
*/
function withdrawAll() external;
/**
* @dev Returns the current balance of the given asset.
*/
function checkBalance(address _asset)
external
view
returns (uint256 balance);
/**
* @dev Returns bool indicating whether strategy supports asset.
*/
function supportsAsset(address _asset) external view returns (bool);
/**
* @dev Collect reward tokens from the Strategy.
*/
function collectRewardTokens() external;
/**
* @dev The address array of the reward tokens for the Strategy.
*/
function getRewardTokenAddresses() external view returns (address[] memory);
function harvesterAddress() external view returns (address);
function transferToken(address token, uint256 amount) external;
function setRewardTokenAddresses(address[] calldata _rewardTokenAddresses)
external;
}
"
},
"contracts/interfaces/IVault.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import { VaultStorage } from "../vault/VaultStorage.sol";
interface IVault {
// slither-disable-start constable-states
event AssetSupported(address _asset);
event AssetDefaultStrategyUpdated(address _asset, address _strategy);
event AssetAllocated(address _asset, address _strategy, uint256 _amount);
event StrategyApproved(address _addr);
event StrategyRemoved(address _addr);
event Mint(address _addr, uint256 _value);
event Redeem(address _addr, uint256 _value);
event CapitalPaused();
event CapitalUnpaused();
event RebasePaused();
event RebaseUnpaused();
event VaultBufferUpdated(uint256 _vaultBuffer);
event RedeemFeeUpdated(uint256 _redeemFeeBps);
event PriceProviderUpdated(address _priceProvider);
event AllocateThresholdUpdated(uint256 _threshold);
event RebaseThresholdUpdated(uint256 _threshold);
event StrategistUpdated(address _address);
event MaxSupplyDiffChanged(uint256 maxSupplyDiff);
event YieldDistribution(address _to, uint256 _yield, uint256 _fee);
event TrusteeFeeBpsChanged(uint256 _basis);
event TrusteeAddressChanged(address _address);
event SwapperChanged(address _address);
event SwapAllowedUndervalueChanged(uint256 _basis);
event SwapSlippageChanged(address _asset, uint256 _basis);
event Swapped(
address indexed _fromAsset,
address indexed _toAsset,
uint256 _fromAssetAmount,
uint256 _toAssetAmount
);
event StrategyAddedToMintWhitelist(address indexed strategy);
event StrategyRemovedFromMintWhitelist(address indexed strategy);
event DripperChanged(address indexed _dripper);
event WithdrawalRequested(
address indexed _withdrawer,
uint256 indexed _requestId,
uint256 _amount,
uint256 _queued
);
event WithdrawalClaimed(
address indexed _withdrawer,
uint256 indexed _requestId,
uint256 _amount
);
event WithdrawalClaimable(uint256 _claimable, uint256 _newClaimable);
// Governable.sol
function transferGovernance(address _newGovernor) external;
function claimGovernance() external;
function governor() external view returns (address);
function ADMIN_IMPLEMENTATION() external view returns (address);
// VaultAdmin.sol
function setPriceProvider(address _priceProvider) external;
function priceProvider() external view returns (address);
function setRedeemFeeBps(uint256 _redeemFeeBps) external;
function redeemFeeBps() external view returns (uint256);
function setVaultBuffer(uint256 _vaultBuffer) external;
function vaultBuffer() external view returns (uint256);
function setAutoAllocateThreshold(uint256 _threshold) external;
function autoAllocateThreshold() external view returns (uint256);
function setRebaseThreshold(uint256 _threshold) external;
function rebaseThreshold() external view returns (uint256);
function setStrategistAddr(address _address) external;
function strategistAddr() external view returns (address);
function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;
function maxSupplyDiff() external view returns (uint256);
function setTrusteeAddress(address _address) external;
function trusteeAddress() external view returns (address);
function setTrusteeFeeBps(uint256 _basis) external;
function trusteeFeeBps() external view returns (uint256);
function ousdMetaStrategy() external view returns (address);
function setSwapper(address _swapperAddr) external;
function setSwapAllowedUndervalue(uint16 _percentageBps) external;
function setOracleSlippage(address _asset, uint16 _allowedOracleSlippageBps)
external;
function supportAsset(address _asset, uint8 _unitConversion) external;
function approveStrategy(address _addr) external;
function removeStrategy(address _addr) external;
function setAssetDefaultStrategy(address _asset, address _strategy)
external;
function assetDefaultStrategies(address _asset)
external
view
returns (address);
function pauseRebase() external;
function unpauseRebase() external;
function rebasePaused() external view returns (bool);
function pauseCapital() external;
function unpauseCapital() external;
function capitalPaused() external view returns (bool);
function transferToken(address _asset, uint256 _amount) external;
function priceUnitMint(address asset) external view returns (uint256);
function priceUnitRedeem(address asset) external view returns (uint256);
function withdrawAllFromStrategy(address _strategyAddr) external;
function withdrawAllFromStrategies() external;
function withdrawFromStrategy(
address _strategyFromAddress,
address[] calldata _assets,
uint256[] calldata _amounts
) external;
function depositToStrategy(
address _strategyToAddress,
address[] calldata _assets,
uint256[] calldata _amounts
) external;
// VaultCore.sol
function mint(
address _asset,
uint256 _amount,
uint256 _minimumOusdAmount
) external;
function mintForStrategy(uint256 _amount) external;
function redeem(uint256 _amount, uint256 _minimumUnitAmount) external;
function burnForStrategy(uint256 _amount) external;
function allocate() external;
function rebase() external;
function swapCollateral(
address fromAsset,
address toAsset,
uint256 fromAssetAmount,
uint256 minToAssetAmount,
bytes calldata data
) external returns (uint256 toAssetAmount);
function totalValue() external view returns (uint256 value);
function checkBalance(address _asset) external view returns (uint256);
function calculateRedeemOutputs(uint256 _amount)
external
view
returns (uint256[] memory);
function getAssetCount() external view returns (uint256);
function getAssetConfig(address _asset)
external
view
returns (VaultStorage.Asset memory config);
function getAllAssets() external view returns (address[] memory);
function getStrategyCount() external view returns (uint256);
function swapper() external view returns (address);
function allowedSwapUndervalue() external view returns (uint256);
function getAllStrategies() external view returns (address[] memory);
function isSupportedAsset(address _asset) external view returns (bool);
function netOusdMintForStrategyThreshold() external view returns (uint256);
function setOusdMetaStrategy(address _ousdMetaStrategy) external;
function setNetOusdMintForStrategyThreshold(uint256 _threshold) external;
function netOusdMintedForStrategy() external view returns (int256);
function setDripper(address _dripper) external;
function dripper() external view returns (address);
function weth() external view returns (address);
function cacheWETHAssetIndex() external;
function wethAssetIndex() external view returns (uint256);
function initialize(address, address) external;
function setAdminImpl(address) external;
function removeAsset(address _asset) external;
// These are OETH specific functions
function addWithdrawalQueueLiquidity() external;
function requestWithdrawal(uint256 _amount)
external
returns (uint256 requestId, uint256 queued);
function claimWithdrawal(uint256 requestId)
external
returns (uint256 amount);
function claimWithdrawals(uint256[] memory requestIds)
external
returns (uint256[] memory amounts, uint256 totalAmount);
function withdrawalQueueMetadata()
external
view
returns (VaultStorage.WithdrawalQueueMetadata memory);
function withdrawalRequests(uint256 requestId)
external
view
returns (VaultStorage.WithdrawalRequest memory);
// OETHb specific functions
function addStrategyToMintWhitelist(address strategyAddr) external;
function removeStrategyFromMintWhitelist(address strategyAddr) external;
function isMintWhitelistedStrategy(address strategyAddr)
external
view
returns (bool);
function withdrawalClaimDelay() external view returns (uint256);
function setWithdrawalClaimDelay(uint256 newDelay) external;
function lastRebase() external view returns (uint64);
function dripDuration() external view returns (uint64);
function setDripDuration(uint256 _dripDuration) external;
function rebasePerSecondMax() external view returns (uint64);
function setRebaseRateMax(uint256 yearlyApr) external;
function rebasePerSecondTarget() external view returns (uint64);
function previewYield() external view returns (uint256 yield);
// slither-disable-end constable-states
}
"
},
"contracts/interfaces/IWETH9.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IWETH9 {
event Approval(address indexed src, address indexed guy, uint256 wad);
event Deposit(address indexed dst, uint256 wad);
event Transfer(address indexed src, address indexed dst, uint256 wad);
event Withdrawal(address indexed src, uint256 wad);
function allowance(address, address) external view returns (uint256);
function approve(address guy, uint256 wad) external returns (bool);
function balanceOf(address) external view returns (uint256);
function decimals() external view returns (uint8);
function deposit() external payable;
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function totalSupply() external view returns (uint256);
function transfer(address dst, uint256 wad) external returns (bool);
function transferFrom(
address src,
address dst,
uint256 wad
) external returns (bool);
function withdraw(uint256 wad) external;
}
"
},
"contracts/strategies/NativeStaking/CompoundingStakingSSVStrategy.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { InitializableAbstractStrategy } from "../../utils/InitializableAbstractStrategy.sol";
import { IWETH9 } from "../../interfaces/IWETH9.sol";
import { CompoundingValidatorManager } from "./CompoundingValidatorManager.sol";
/// @title Compounding Staking SSV Strategy
/// @notice Strategy to deploy funds into DVT validators powered by the SSV Network
/// @author Origin Protocol Inc
contract CompoundingStakingSSVStrategy is
CompoundingValidatorManager,
InitializableAbstractStrategy
{
/// @notice SSV ERC20 token that serves as a payment for operating SSV validators
address public immutable SSV_TOKEN;
// For future use
uint256[50] private __gap;
/// @param _baseConfig Base strategy config with
/// `platformAddress` not used so empty address
/// `vaultAddress` the address of the OETH Vault contract
/// @param _wethAddress Address of the WETH Token contract
/// @param _ssvToken Address of the SSV Token contract
/// @param _ssvNetwork Address of the SSV Network contract
/// @param _beaconChainDepositContract Address of the beacon chain deposit contract
/// @param _beaconProofs Address of the Beacon Proofs contract that verifies beacon chain data
/// @param _beaconGenesisTimestamp The timestamp of the Beacon chain's genesis.
constructor(
BaseStrategyConfig memory _baseConfig,
address _wethAddress,
address _ssvToken,
address _ssvNetwork,
address _beaconChainDepositContract,
address _beaconProofs,
uint64 _beaconGenesisTimestamp
)
InitializableAbstractStrategy(_baseConfig)
CompoundingValidatorManager(
_wethAddress,
_baseConfig.vaultAddress,
_beaconChainDepositContract,
_ssvNetwork,
_beaconProofs,
_beaconGenesisTimestamp
)
{
SSV_TOKEN = _ssvToken;
// Make sure nobody owns the implementation contract
_setGovernor(address(0));
}
/// @notice Set up initial internal state including
/// 1. approving the SSVNetwork to transfer SSV tokens from this strategy contract
/// @param _rewardTokenAddresses Not used so empty array
/// @param _assets Not used so empty array
/// @param _pTokens Not used so empty array
function initialize(
address[] memory _rewardTokenAddresses,
address[] memory _assets,
address[] memory _pTokens
) external onlyGovernor initializer {
InitializableAbstractStrategy._initialize(
_rewardTokenAddresses,
_assets,
_pTokens
);
safeApproveAllTokens();
}
///
Submitted on: 2025-10-27 12:56:44
Comments
Log in to comment.
No comments yet.