@sablier/bob 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/LICENSE-BUSL.md +82 -0
- package/LICENSE-GPL.md +470 -0
- package/LICENSE.md +9 -0
- package/README.md +81 -0
- package/artifacts/BobVaultShare.json +936 -0
- package/artifacts/SablierBob.json +1683 -0
- package/artifacts/SablierEscrow.json +1316 -0
- package/artifacts/SablierLidoAdapter.json +1649 -0
- package/artifacts/erc20/IERC20.json +226 -0
- package/artifacts/interfaces/IBobVaultShare.json +393 -0
- package/artifacts/interfaces/ISablierBob.json +1171 -0
- package/artifacts/interfaces/ISablierEscrow.json +999 -0
- package/artifacts/interfaces/ISablierLidoAdapter.json +1141 -0
- package/artifacts/interfaces/external/ICurveStETHPool.json +128 -0
- package/artifacts/interfaces/external/ILidoWithdrawalQueue.json +209 -0
- package/artifacts/interfaces/external/IStETH.json +262 -0
- package/artifacts/interfaces/external/IWETH9.json +259 -0
- package/artifacts/interfaces/external/IWstETH.json +311 -0
- package/artifacts/libraries/Errors.json +868 -0
- package/package.json +68 -0
- package/src/BobVaultShare.sol +119 -0
- package/src/SablierBob.sol +543 -0
- package/src/SablierEscrow.sol +288 -0
- package/src/SablierLidoAdapter.sol +549 -0
- package/src/abstracts/SablierBobState.sol +156 -0
- package/src/abstracts/SablierEscrowState.sol +159 -0
- package/src/interfaces/IBobVaultShare.sol +51 -0
- package/src/interfaces/ISablierBob.sol +261 -0
- package/src/interfaces/ISablierBobAdapter.sol +157 -0
- package/src/interfaces/ISablierBobState.sol +74 -0
- package/src/interfaces/ISablierEscrow.sol +148 -0
- package/src/interfaces/ISablierEscrowState.sol +77 -0
- package/src/interfaces/ISablierLidoAdapter.sol +110 -0
- package/src/interfaces/external/ICurveStETHPool.sol +31 -0
- package/src/interfaces/external/ILidoWithdrawalQueue.sol +67 -0
- package/src/interfaces/external/IStETH.sol +18 -0
- package/src/interfaces/external/IWETH9.sol +19 -0
- package/src/interfaces/external/IWstETH.sol +32 -0
- package/src/libraries/Errors.sol +189 -0
- package/src/types/Bob.sol +49 -0
- package/src/types/Escrow.sol +49 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
pragma solidity >=0.8.22;
|
|
3
|
+
|
|
4
|
+
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
5
|
+
import { UD60x18 } from "@prb/math/src/UD60x18.sol";
|
|
6
|
+
import { IComptrollerable } from "@sablier/evm-utils/src/interfaces/IComptrollerable.sol";
|
|
7
|
+
|
|
8
|
+
/// @title ISablierBobAdapter
|
|
9
|
+
/// @notice Base interface for adapters used by the SablierBob protocol for generating yield.
|
|
10
|
+
interface ISablierBobAdapter is IComptrollerable, IERC165 {
|
|
11
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
12
|
+
EVENTS
|
|
13
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
14
|
+
|
|
15
|
+
/// @notice Emitted when the comptroller sets a new yield fee.
|
|
16
|
+
event SetYieldFee(UD60x18 previousFee, UD60x18 newFee);
|
|
17
|
+
|
|
18
|
+
/// @notice Emitted when tokens are staked for a user in a vault.
|
|
19
|
+
event Stake(uint256 indexed vaultId, address indexed user, uint256 depositAmount, uint256 wrappedStakedAmount);
|
|
20
|
+
|
|
21
|
+
/// @notice Emitted when staked token attribution is transferred between users.
|
|
22
|
+
event TransferStakedTokens(uint256 indexed vaultId, address indexed from, address indexed to, uint256 amount);
|
|
23
|
+
|
|
24
|
+
/// @notice Emitted when all staked tokens in a vault are converted back to the deposit token.
|
|
25
|
+
event UnstakeFullAmount(uint256 indexed vaultId, uint128 totalStakedAmount, uint128 amountReceivedFromUnstaking);
|
|
26
|
+
|
|
27
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
28
|
+
READ-ONLY FUNCTIONS
|
|
29
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
30
|
+
|
|
31
|
+
/// @notice Returns the maximum yield fee, denominated in UD60x18, where 1e18 = 100%.
|
|
32
|
+
/// @dev This is a constant state variable.
|
|
33
|
+
function MAX_FEE() external view returns (UD60x18);
|
|
34
|
+
|
|
35
|
+
/// @notice Returns the address of the SablierBob contract.
|
|
36
|
+
/// @dev This is an immutable state variable.
|
|
37
|
+
function SABLIER_BOB() external view returns (address);
|
|
38
|
+
|
|
39
|
+
/// @notice Returns the current global fee on yield for new vaults, denominated in UD60x18, where 1e18 = 100%.
|
|
40
|
+
function feeOnYield() external view returns (UD60x18);
|
|
41
|
+
|
|
42
|
+
/// @notice Returns the total amount of yield-bearing tokens held in a vault.
|
|
43
|
+
/// @param vaultId The ID of the vault.
|
|
44
|
+
/// @return The total amount of yield-bearing tokens in the vault.
|
|
45
|
+
function getTotalYieldBearingTokenBalance(uint256 vaultId) external view returns (uint128);
|
|
46
|
+
|
|
47
|
+
/// @notice Returns the yield fee stored for a specific vault.
|
|
48
|
+
/// @param vaultId The ID of the vault.
|
|
49
|
+
/// @return The yield fee for the vault denominated in UD60x18, where 1e18 = 100%.
|
|
50
|
+
function getVaultYieldFee(uint256 vaultId) external view returns (UD60x18);
|
|
51
|
+
|
|
52
|
+
/// @notice Returns the amount of yield-bearing tokens held for a specific user in a vault.
|
|
53
|
+
/// @param vaultId The ID of the vault.
|
|
54
|
+
/// @param user The address of the user.
|
|
55
|
+
/// @return The amount of yield-bearing tokens the user has claim to.
|
|
56
|
+
function getYieldBearingTokenBalanceFor(uint256 vaultId, address user) external view returns (uint128);
|
|
57
|
+
|
|
58
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
59
|
+
STATE-CHANGING FUNCTIONS
|
|
60
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
61
|
+
|
|
62
|
+
/// @notice Processes a user's token redemption by calculating the transfer amount, clearing the user's
|
|
63
|
+
/// yield-bearing token balance, and returning the amounts.
|
|
64
|
+
///
|
|
65
|
+
/// Notes:
|
|
66
|
+
/// - The user's yield-bearing token balance is decremented after calculating the transfer amount. This does not
|
|
67
|
+
/// decrement the vault total as it is used in the calculation of the transfer amount for other users.
|
|
68
|
+
///
|
|
69
|
+
/// Requirements:
|
|
70
|
+
/// - The caller must be the SablierBob contract.
|
|
71
|
+
///
|
|
72
|
+
/// @param vaultId The ID of the vault.
|
|
73
|
+
/// @param user The address of the user.
|
|
74
|
+
/// @param shareBalance The user's share balance in the vault.
|
|
75
|
+
/// @return transferAmount The amount to transfer to the user.
|
|
76
|
+
/// @return feeAmountDeductedFromYield The fee amount taken from the yield.
|
|
77
|
+
function processRedemption(
|
|
78
|
+
uint256 vaultId,
|
|
79
|
+
address user,
|
|
80
|
+
uint128 shareBalance
|
|
81
|
+
)
|
|
82
|
+
external
|
|
83
|
+
returns (uint128 transferAmount, uint128 feeAmountDeductedFromYield);
|
|
84
|
+
|
|
85
|
+
/// @notice Register a new vault with the adapter and snapshot the current fee on yield.
|
|
86
|
+
///
|
|
87
|
+
/// Requirements:
|
|
88
|
+
/// - The caller must be the SablierBob contract.
|
|
89
|
+
///
|
|
90
|
+
/// @param vaultId The ID of the newly created vault.
|
|
91
|
+
function registerVault(uint256 vaultId) external;
|
|
92
|
+
|
|
93
|
+
/// @notice Sets the fee on yield for future vaults.
|
|
94
|
+
///
|
|
95
|
+
/// @dev Emits a {SetYieldFee} event.
|
|
96
|
+
///
|
|
97
|
+
/// Notes:
|
|
98
|
+
/// - This only affects future vaults, fee is not updated for existing vaults.
|
|
99
|
+
///
|
|
100
|
+
/// Requirements:
|
|
101
|
+
/// - The caller must be the comptroller.
|
|
102
|
+
/// - `newFee` must not exceed MAX_FEE.
|
|
103
|
+
///
|
|
104
|
+
/// @param newFee The new yield fee as UD60x18 where 1e18 = 100%.
|
|
105
|
+
function setYieldFee(UD60x18 newFee) external;
|
|
106
|
+
|
|
107
|
+
/// @notice Stakes tokens deposited by a user in a vault, converting them to yield-bearing tokens.
|
|
108
|
+
///
|
|
109
|
+
/// @dev Emits a {Stake} event.
|
|
110
|
+
///
|
|
111
|
+
/// Requirements:
|
|
112
|
+
/// - The caller must be the SablierBob contract.
|
|
113
|
+
/// - The tokens must have been transferred to this contract.
|
|
114
|
+
///
|
|
115
|
+
/// @param vaultId The ID of the vault.
|
|
116
|
+
/// @param user The address of the user depositing the tokens.
|
|
117
|
+
/// @param amount The amount of tokens to stake.
|
|
118
|
+
function stake(uint256 vaultId, address user, uint256 amount) external;
|
|
119
|
+
|
|
120
|
+
/// @notice Converts all yield-bearing tokens in a vault back to deposit tokens after settlement.
|
|
121
|
+
///
|
|
122
|
+
/// @dev Emits an {UnstakeFullAmount} event.
|
|
123
|
+
///
|
|
124
|
+
/// Notes:
|
|
125
|
+
/// - This should only be called once per vault after settlement.
|
|
126
|
+
///
|
|
127
|
+
/// Requirements:
|
|
128
|
+
/// - The caller must be the SablierBob contract.
|
|
129
|
+
///
|
|
130
|
+
/// @param vaultId The ID of the vault.
|
|
131
|
+
/// @return wrappedTokenBalance The total amount of yield-bearing tokens that were in the vault.
|
|
132
|
+
/// @return amountReceivedFromUnstaking The total amount of tokens received from unstaking the yield-bearing tokens.
|
|
133
|
+
function unstakeFullAmount(uint256 vaultId)
|
|
134
|
+
external
|
|
135
|
+
returns (uint128 wrappedTokenBalance, uint128 amountReceivedFromUnstaking);
|
|
136
|
+
|
|
137
|
+
/// @notice Updates staked token balance of a user when vault shares are transferred.
|
|
138
|
+
///
|
|
139
|
+
/// Requirements:
|
|
140
|
+
/// - The caller must be the SablierBob contract.
|
|
141
|
+
/// - `userShareBalanceBeforeTransfer` must not be zero.
|
|
142
|
+
/// - The calculated wstETH transfer amount must not be zero.
|
|
143
|
+
///
|
|
144
|
+
/// @param vaultId The ID of the vault.
|
|
145
|
+
/// @param from The address transferring vault shares.
|
|
146
|
+
/// @param to The address receiving vault shares.
|
|
147
|
+
/// @param shareAmountTransferred The number of vault shares being transferred.
|
|
148
|
+
/// @param userShareBalanceBeforeTransfer The sender's vault share balance before the transfer.
|
|
149
|
+
function updateStakedTokenBalance(
|
|
150
|
+
uint256 vaultId,
|
|
151
|
+
address from,
|
|
152
|
+
address to,
|
|
153
|
+
uint256 shareAmountTransferred,
|
|
154
|
+
uint256 userShareBalanceBeforeTransfer
|
|
155
|
+
)
|
|
156
|
+
external;
|
|
157
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
pragma solidity >=0.8.22;
|
|
3
|
+
|
|
4
|
+
import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";
|
|
5
|
+
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
6
|
+
|
|
7
|
+
import { Bob } from "../types/Bob.sol";
|
|
8
|
+
import { IBobVaultShare } from "./IBobVaultShare.sol";
|
|
9
|
+
import { ISablierBobAdapter } from "./ISablierBobAdapter.sol";
|
|
10
|
+
|
|
11
|
+
/// @title ISablierBobState
|
|
12
|
+
/// @notice Contract with state variables for the {SablierBob} contract, their respective getters and modifiers.
|
|
13
|
+
interface ISablierBobState {
|
|
14
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
15
|
+
READ-ONLY FUNCTIONS
|
|
16
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
17
|
+
|
|
18
|
+
/// @notice Returns the adapter configured for a specific vault.
|
|
19
|
+
/// @dev Reverts if `vaultId` references a null vault.
|
|
20
|
+
function getAdapter(uint256 vaultId) external view returns (ISablierBobAdapter adapter);
|
|
21
|
+
|
|
22
|
+
/// @notice Returns the default adapter for a given token.
|
|
23
|
+
/// @dev Zero address means no adapter is set.
|
|
24
|
+
/// @param token The ERC-20 token to query the default adapter for.
|
|
25
|
+
/// @return adapter The default adapter for the token.
|
|
26
|
+
function getDefaultAdapterFor(IERC20 token) external view returns (ISablierBobAdapter adapter);
|
|
27
|
+
|
|
28
|
+
/// @notice Returns the timestamp when the vault expires.
|
|
29
|
+
/// @dev Reverts if `vaultId` references a null vault.
|
|
30
|
+
function getExpiry(uint256 vaultId) external view returns (uint40 expiry);
|
|
31
|
+
|
|
32
|
+
/// @notice Returns the timestamp when the oracle price was last synced for a vault.
|
|
33
|
+
/// @dev Reverts if `vaultId` references a null vault.
|
|
34
|
+
function getLastSyncedAt(uint256 vaultId) external view returns (uint40 lastSyncedAt);
|
|
35
|
+
|
|
36
|
+
/// @notice Returns the oracle price stored for a vault.
|
|
37
|
+
/// @dev Reverts if `vaultId` references a null vault.
|
|
38
|
+
function getLastSyncedPrice(uint256 vaultId) external view returns (uint128 lastSyncedPrice);
|
|
39
|
+
|
|
40
|
+
/// @notice Returns the oracle address set for a vault.
|
|
41
|
+
/// @dev Reverts if `vaultId` references a null vault.
|
|
42
|
+
function getOracle(uint256 vaultId) external view returns (AggregatorV3Interface oracle);
|
|
43
|
+
|
|
44
|
+
/// @notice Returns the address of the ERC-20 share token for a vault.
|
|
45
|
+
/// @dev Reverts if `vaultId` references a null vault.
|
|
46
|
+
function getShareToken(uint256 vaultId) external view returns (IBobVaultShare shareToken);
|
|
47
|
+
|
|
48
|
+
/// @notice Returns the target price at which the vault settles.
|
|
49
|
+
/// @dev Reverts if `vaultId` references a null vault.
|
|
50
|
+
function getTargetPrice(uint256 vaultId) external view returns (uint128 targetPrice);
|
|
51
|
+
|
|
52
|
+
/// @notice Returns the ERC-20 token accepted for deposits in a vault.
|
|
53
|
+
/// @dev Reverts if `vaultId` references a null vault.
|
|
54
|
+
function getUnderlyingToken(uint256 vaultId) external view returns (IERC20 token);
|
|
55
|
+
|
|
56
|
+
/// @notice Returns whether the vault tokens are staked in an adapter.
|
|
57
|
+
/// @dev Reverts if `vaultId` references a null vault.
|
|
58
|
+
function isStakedInAdapter(uint256 vaultId) external view returns (bool stakedInAdapter);
|
|
59
|
+
|
|
60
|
+
/// @notice Retrieves the address of the ERC-20 interface of the native token, if it exists.
|
|
61
|
+
/// @dev The native tokens on some chains have a dual interface as ERC-20. For example, on Polygon the $POL token
|
|
62
|
+
/// is the native token and has an ERC-20 version at 0x0000000000000000000000000000000000001010. This means
|
|
63
|
+
/// that `address(this).balance` returns the same value as `balanceOf(address(this))`. To avoid any unintended
|
|
64
|
+
/// behavior, these tokens cannot be used in Sablier. As an alternative, users can use the Wrapped version of the
|
|
65
|
+
/// token, i.e. WMATIC, which is a standard ERC-20 token.
|
|
66
|
+
function nativeToken() external view returns (address);
|
|
67
|
+
|
|
68
|
+
/// @notice Counter for vault IDs, incremented every time a new vault is created.
|
|
69
|
+
function nextVaultId() external view returns (uint256);
|
|
70
|
+
|
|
71
|
+
/// @notice Returns the vault status.
|
|
72
|
+
/// @dev Reverts if `vaultId` references a null vault.
|
|
73
|
+
function statusOf(uint256 vaultId) external view returns (Bob.Status status);
|
|
74
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
pragma solidity >=0.8.22;
|
|
3
|
+
|
|
4
|
+
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
5
|
+
import { UD60x18 } from "@prb/math/src/UD60x18.sol";
|
|
6
|
+
import { IComptrollerable } from "@sablier/evm-utils/src/interfaces/IComptrollerable.sol";
|
|
7
|
+
|
|
8
|
+
import { ISablierEscrowState } from "./ISablierEscrowState.sol";
|
|
9
|
+
|
|
10
|
+
/// @title ISablierEscrow
|
|
11
|
+
/// @notice A peer-to-peer token swap protocol that allows users to swap ERC-20 tokens with each other.
|
|
12
|
+
interface ISablierEscrow is IComptrollerable, ISablierEscrowState {
|
|
13
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
14
|
+
EVENTS
|
|
15
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
16
|
+
|
|
17
|
+
/// @notice Emitted when an order is cancelled by the seller.
|
|
18
|
+
event CancelOrder(uint256 indexed orderId, address indexed seller, uint128 sellAmount);
|
|
19
|
+
|
|
20
|
+
/// @notice Emitted when a new order is created.
|
|
21
|
+
event CreateOrder(
|
|
22
|
+
uint256 indexed orderId,
|
|
23
|
+
address indexed seller,
|
|
24
|
+
address indexed buyer,
|
|
25
|
+
IERC20 sellToken,
|
|
26
|
+
IERC20 buyToken,
|
|
27
|
+
uint128 sellAmount,
|
|
28
|
+
uint128 minBuyAmount,
|
|
29
|
+
uint40 expiryTime
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
/// @notice Emitted when an order is filled.
|
|
33
|
+
event FillOrder(
|
|
34
|
+
uint256 indexed orderId,
|
|
35
|
+
address indexed buyer,
|
|
36
|
+
address indexed seller,
|
|
37
|
+
uint128 sellAmount,
|
|
38
|
+
uint128 buyAmount,
|
|
39
|
+
uint128 feeDeductedFromBuyerAmount,
|
|
40
|
+
uint128 feeDeductedFromSellerAmount
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
/// @notice Emitted when the native token address is set by the comptroller.
|
|
44
|
+
event SetNativeToken(address indexed comptroller, address nativeToken);
|
|
45
|
+
|
|
46
|
+
/// @notice Emitted when the trade fee is updated.
|
|
47
|
+
event SetTradeFee(address indexed caller, UD60x18 previousTradeFee, UD60x18 newTradeFee);
|
|
48
|
+
|
|
49
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
50
|
+
STATE-CHANGING FUNCTIONS
|
|
51
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
52
|
+
|
|
53
|
+
/// @notice Cancels an order and returns the escrowed tokens to the caller.
|
|
54
|
+
///
|
|
55
|
+
/// @dev Emits a {CancelOrder} event.
|
|
56
|
+
///
|
|
57
|
+
/// Requirements:
|
|
58
|
+
/// - The order must exist.
|
|
59
|
+
/// - The order status must either be OPEN or EXPIRED.
|
|
60
|
+
/// - The caller must be the seller of the order.
|
|
61
|
+
///
|
|
62
|
+
/// @param orderId The order ID to cancel.
|
|
63
|
+
function cancelOrder(uint256 orderId) external;
|
|
64
|
+
|
|
65
|
+
/// @notice Creates a new order for a peer-to-peer token swap.
|
|
66
|
+
///
|
|
67
|
+
/// @dev Emits a {CreateOrder} event.
|
|
68
|
+
///
|
|
69
|
+
/// Requirements:
|
|
70
|
+
/// - `sellToken` must not be the zero address.
|
|
71
|
+
/// - `buyToken` must not be the zero address.
|
|
72
|
+
/// - `sellToken` and `buyToken` must not be the same token.
|
|
73
|
+
/// - `sellAmount` must be greater than zero.
|
|
74
|
+
/// - `minBuyAmount` must be greater than zero.
|
|
75
|
+
/// - If `expiryTime` is non-zero, it must be in the future. Zero is sentinel for orders that never expire.
|
|
76
|
+
/// - The caller must have approved this contract to transfer at least `sellAmount` of `sellToken`.
|
|
77
|
+
///
|
|
78
|
+
/// @param sellToken The address of the ERC-20 token to sell.
|
|
79
|
+
/// @param sellAmount The amount of sell token to exchange.
|
|
80
|
+
/// @param buyToken The address of the ERC-20 token to receive.
|
|
81
|
+
/// @param minBuyAmount The minimum amount of buy token to fill this trade.
|
|
82
|
+
/// @param buyer The designated counterparty address specified by the seller. If its zero address, the order can be
|
|
83
|
+
/// filled by anyone.
|
|
84
|
+
/// @param expiryTime The Unix timestamp when the order expires. Zero is sentinel for orders that never expire.
|
|
85
|
+
/// @return orderId The order ID of the newly created order.
|
|
86
|
+
function createOrder(
|
|
87
|
+
IERC20 sellToken,
|
|
88
|
+
uint128 sellAmount,
|
|
89
|
+
IERC20 buyToken,
|
|
90
|
+
uint128 minBuyAmount,
|
|
91
|
+
address buyer,
|
|
92
|
+
uint40 expiryTime
|
|
93
|
+
)
|
|
94
|
+
external
|
|
95
|
+
returns (uint256 orderId);
|
|
96
|
+
|
|
97
|
+
/// @notice Fill an open order.
|
|
98
|
+
///
|
|
99
|
+
/// @dev Emits an {FillOrder} event.
|
|
100
|
+
///
|
|
101
|
+
/// Requirements:
|
|
102
|
+
/// - The order must exist.
|
|
103
|
+
/// - The order must be in OPEN status.
|
|
104
|
+
/// - If the order has buyer specified, the caller must be the buyer.
|
|
105
|
+
/// - `buyAmount` must be greater than or equal to the `minBuyAmount`.
|
|
106
|
+
/// - The caller must have approved this contract to transfer at least `buyAmount` of `buyToken`.
|
|
107
|
+
///
|
|
108
|
+
/// @param orderId The order ID to fill.
|
|
109
|
+
/// @param buyAmount The amount of buy token to exchange.
|
|
110
|
+
/// @return amountToTransferToSeller The amount of buy token to transfer to the seller after deducting fees.
|
|
111
|
+
/// @return amountToTransferToBuyer The amount of sell token to transfer to the buyer after deducting fees.
|
|
112
|
+
/// @return feeDeductedFromBuyerAmount The amount of sell token deducted from the buyer's amount as fees.
|
|
113
|
+
/// @return feeDeductedFromSellerAmount The amount of buy token deducted from the seller's amount as fees.
|
|
114
|
+
function fillOrder(
|
|
115
|
+
uint256 orderId,
|
|
116
|
+
uint128 buyAmount
|
|
117
|
+
)
|
|
118
|
+
external
|
|
119
|
+
returns (
|
|
120
|
+
uint128 amountToTransferToSeller,
|
|
121
|
+
uint128 amountToTransferToBuyer,
|
|
122
|
+
uint128 feeDeductedFromBuyerAmount,
|
|
123
|
+
uint128 feeDeductedFromSellerAmount
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
/// @notice Sets the native token address. Once set, it cannot be changed.
|
|
127
|
+
/// @dev For more information, see the documentation for {nativeToken}.
|
|
128
|
+
///
|
|
129
|
+
/// Emits a {SetNativeToken} event.
|
|
130
|
+
///
|
|
131
|
+
/// Requirements:
|
|
132
|
+
/// - `msg.sender` must be the comptroller.
|
|
133
|
+
/// - `newNativeToken` must not be zero address.
|
|
134
|
+
/// - The native token must not be already set.
|
|
135
|
+
/// @param newNativeToken The address of the native token.
|
|
136
|
+
function setNativeToken(address newNativeToken) external;
|
|
137
|
+
|
|
138
|
+
/// @notice Sets the fee to apply on each trade.
|
|
139
|
+
///
|
|
140
|
+
/// @dev Emits a {SetTradeFee} event.
|
|
141
|
+
///
|
|
142
|
+
/// Requirements:
|
|
143
|
+
/// - The caller must be the comptroller.
|
|
144
|
+
/// - `newTradeFee` must not exceed the maximum trade fee.
|
|
145
|
+
///
|
|
146
|
+
/// @param newTradeFee The new trade fee to set, denominated in UD60x18, where 1e18 = 100%.
|
|
147
|
+
function setTradeFee(UD60x18 newTradeFee) external;
|
|
148
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
pragma solidity >=0.8.22;
|
|
3
|
+
|
|
4
|
+
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
5
|
+
import { UD60x18 } from "@prb/math/src/UD60x18.sol";
|
|
6
|
+
|
|
7
|
+
import { Escrow } from "../types/Escrow.sol";
|
|
8
|
+
|
|
9
|
+
/// @title ISablierEscrowState
|
|
10
|
+
/// @notice Interface containing state variables (storage and constants) for the {SablierEscrow} contract, along with
|
|
11
|
+
/// their respective getters.
|
|
12
|
+
interface ISablierEscrowState {
|
|
13
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
14
|
+
READ-ONLY FUNCTIONS
|
|
15
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
16
|
+
|
|
17
|
+
/// @notice Returns the maximum trade fee that can be applied, denominated in UD60x18, where 1e18 = 100%.
|
|
18
|
+
/// @dev This is a constant state variable.
|
|
19
|
+
function MAX_TRADE_FEE() external view returns (UD60x18);
|
|
20
|
+
|
|
21
|
+
/// @notice Retrieves the buyer address for the given order. If its zero address, the order can be filled by any
|
|
22
|
+
/// address.
|
|
23
|
+
/// @dev Reverts if `orderId` references a null order.
|
|
24
|
+
function getBuyer(uint256 orderId) external view returns (address buyer);
|
|
25
|
+
|
|
26
|
+
/// @notice Retrieves the address of the ERC-20 token the seller wants to receive.
|
|
27
|
+
/// @dev Reverts if `orderId` references a null order.
|
|
28
|
+
function getBuyToken(uint256 orderId) external view returns (IERC20 buyToken);
|
|
29
|
+
|
|
30
|
+
/// @notice Retrieves the time when the order expires and can no longer be filled. Zero is sentinel for orders that
|
|
31
|
+
/// never expire.
|
|
32
|
+
/// @dev Reverts if `orderId` references a null order.
|
|
33
|
+
function getExpiryTime(uint256 orderId) external view returns (uint40 expiryTime);
|
|
34
|
+
|
|
35
|
+
/// @notice Retrieves the minimum amount of buy token required to fill the order.
|
|
36
|
+
/// @dev Reverts if `orderId` references a null order.
|
|
37
|
+
function getMinBuyAmount(uint256 orderId) external view returns (uint128 minBuyAmount);
|
|
38
|
+
|
|
39
|
+
/// @notice Retrieves the amount of sell token that the seller is willing to sell.
|
|
40
|
+
/// @dev Reverts if `orderId` references a null order.
|
|
41
|
+
function getSellAmount(uint256 orderId) external view returns (uint128 sellAmount);
|
|
42
|
+
|
|
43
|
+
/// @notice Retrieves the address of the seller who created the order.
|
|
44
|
+
/// @dev Reverts if `orderId` references a null order.
|
|
45
|
+
function getSeller(uint256 orderId) external view returns (address seller);
|
|
46
|
+
|
|
47
|
+
/// @notice Retrieves the address of the ERC-20 token that the seller is willing to sell.
|
|
48
|
+
/// @dev Reverts if `orderId` references a null order.
|
|
49
|
+
function getSellToken(uint256 orderId) external view returns (IERC20 sellToken);
|
|
50
|
+
|
|
51
|
+
/// @notice Retrieves the address of the ERC-20 interface of the native token, if it exists.
|
|
52
|
+
/// @dev The native tokens on some chains have a dual interface as ERC-20. For example, on Polygon the $POL token
|
|
53
|
+
/// is the native token and has an ERC-20 version at 0x0000000000000000000000000000000000001010. This means
|
|
54
|
+
/// that `address(this).balance` returns the same value as `balanceOf(address(this))`. To avoid any unintended
|
|
55
|
+
/// behavior, these tokens cannot be used in Sablier. As an alternative, users can use the Wrapped version of the
|
|
56
|
+
/// token, i.e. WMATIC, which is a standard ERC-20 token.
|
|
57
|
+
function nativeToken() external view returns (address);
|
|
58
|
+
|
|
59
|
+
/// @notice Counter for order IDs. It's incremented every time a new order is created.
|
|
60
|
+
function nextOrderId() external view returns (uint256);
|
|
61
|
+
|
|
62
|
+
/// @notice Returns the status of the order.
|
|
63
|
+
/// @dev Reverts if `orderId` references a null order.
|
|
64
|
+
function statusOf(uint256 orderId) external view returns (Escrow.Status status);
|
|
65
|
+
|
|
66
|
+
/// @notice Returns the fee percentage, denominated in UD60x18, where 1e18 = 100%.
|
|
67
|
+
/// @dev This trade fee is taken from both the sell and buy amounts in their respective tokens.
|
|
68
|
+
function tradeFee() external view returns (UD60x18);
|
|
69
|
+
|
|
70
|
+
/// @notice Retrieves a flag indicating whether the order was canceled.
|
|
71
|
+
/// @dev Reverts if `orderId` references a null order.
|
|
72
|
+
function wasCanceled(uint256 orderId) external view returns (bool);
|
|
73
|
+
|
|
74
|
+
/// @notice Retrieves a flag indicating whether the order was filled.
|
|
75
|
+
/// @dev Reverts if `orderId` references a null order.
|
|
76
|
+
function wasFilled(uint256 orderId) external view returns (bool);
|
|
77
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
pragma solidity >=0.8.22;
|
|
3
|
+
|
|
4
|
+
import { UD60x18 } from "@prb/math/src/UD60x18.sol";
|
|
5
|
+
|
|
6
|
+
import { ISablierBobAdapter } from "./ISablierBobAdapter.sol";
|
|
7
|
+
|
|
8
|
+
/// @title ISablierLidoAdapter
|
|
9
|
+
/// @notice Interface for the Lido yield adapter that stakes WETH as wstETH and unstakes it via Curve.
|
|
10
|
+
/// @dev Extends the base adapter interface with Lido and Curve specific functionalities.
|
|
11
|
+
interface ISablierLidoAdapter is ISablierBobAdapter {
|
|
12
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
13
|
+
EVENTS
|
|
14
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
15
|
+
|
|
16
|
+
/// @notice Emitted when the comptroller requests a Lido native withdrawal for a vault.
|
|
17
|
+
event RequestLidoWithdrawal(
|
|
18
|
+
uint256 indexed vaultId,
|
|
19
|
+
address indexed comptroller,
|
|
20
|
+
uint256 wstETHAmount,
|
|
21
|
+
uint256 stETHAmount,
|
|
22
|
+
uint256[] withdrawalRequestIds
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
/// @notice Emitted when the comptroller sets a new slippage tolerance.
|
|
26
|
+
event SetSlippageTolerance(UD60x18 previousTolerance, UD60x18 newTolerance);
|
|
27
|
+
|
|
28
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
29
|
+
READ-ONLY FUNCTIONS
|
|
30
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
31
|
+
|
|
32
|
+
/// @notice Returns the address of the Curve stETH/ETH pool.
|
|
33
|
+
/// @dev This is an immutable state variable.
|
|
34
|
+
function CURVE_POOL() external view returns (address);
|
|
35
|
+
|
|
36
|
+
/// @notice Returns the address of the Lido withdrawal queue contract.
|
|
37
|
+
/// @dev This is an immutable state variable.
|
|
38
|
+
function LIDO_WITHDRAWAL_QUEUE() external view returns (address);
|
|
39
|
+
|
|
40
|
+
/// @notice Returns the maximum slippage tolerance that can be set, denominated in UD60x18, where 1e18 = 100%.
|
|
41
|
+
/// @dev This is a constant state variable.
|
|
42
|
+
function MAX_SLIPPAGE_TOLERANCE() external view returns (UD60x18);
|
|
43
|
+
|
|
44
|
+
/// @notice Returns the address of the stETH contract.
|
|
45
|
+
/// @dev This is an immutable state variable.
|
|
46
|
+
function STETH() external view returns (address);
|
|
47
|
+
|
|
48
|
+
/// @notice Returns the address of the Chainlink stETH/ETH oracle used in the calculation of `minEthOut` slippage.
|
|
49
|
+
/// @dev This is an immutable state variable.
|
|
50
|
+
function STETH_ETH_ORACLE() external view returns (address);
|
|
51
|
+
|
|
52
|
+
/// @notice Returns the address of the WETH contract.
|
|
53
|
+
/// @dev This is an immutable state variable.
|
|
54
|
+
function WETH() external view returns (address);
|
|
55
|
+
|
|
56
|
+
/// @notice Returns the address of the wstETH contract.
|
|
57
|
+
/// @dev This is an immutable state variable.
|
|
58
|
+
function WSTETH() external view returns (address);
|
|
59
|
+
|
|
60
|
+
/// @notice Returns the Lido withdrawal request IDs for a vault.
|
|
61
|
+
/// @dev Multiple request IDs may be generated for a vault if the total amount exceeds the Lido enforced
|
|
62
|
+
/// per-withdrawal limit.
|
|
63
|
+
function getLidoWithdrawalRequestIds(uint256 vaultId) external view returns (uint256[] memory);
|
|
64
|
+
|
|
65
|
+
/// @notice Returns the total WETH received after unstaking for a vault.
|
|
66
|
+
/// @param vaultId The ID of the vault.
|
|
67
|
+
function getWethReceivedAfterUnstaking(uint256 vaultId) external view returns (uint256);
|
|
68
|
+
|
|
69
|
+
/// @notice Returns the current slippage tolerance for Curve swaps, denominated in UD60x18, where 1e18 = 100%.
|
|
70
|
+
function slippageTolerance() external view returns (UD60x18);
|
|
71
|
+
|
|
72
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
73
|
+
STATE-CHANGING FUNCTIONS
|
|
74
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
75
|
+
|
|
76
|
+
/// @notice Requests a native Lido withdrawal for a vault's staked tokens, bypassing the Curve swap.
|
|
77
|
+
///
|
|
78
|
+
/// @dev Emits a {RequestLidoWithdrawal} event.
|
|
79
|
+
///
|
|
80
|
+
/// Notes:
|
|
81
|
+
/// - This unwraps the vault's wstETH to stETH and submits it to Lido's withdrawal queue.
|
|
82
|
+
/// - Once called, the Curve swap is permanently disabled for `vaultId`.
|
|
83
|
+
/// - After the queue finalizes the withdrawal, ETH can be redeemed by calling {unstakeFullAmount}.
|
|
84
|
+
/// - Large amounts are automatically split into multiple requests to comply with Lido's per-request limit.
|
|
85
|
+
///
|
|
86
|
+
/// Requirements:
|
|
87
|
+
/// - The caller must be the comptroller.
|
|
88
|
+
/// - The status of the vault must not be ACTIVE.
|
|
89
|
+
/// - The vault must still be staked in the adapter (not already unstaked via Curve).
|
|
90
|
+
/// - A withdrawal request must not have already been requested for this vault.
|
|
91
|
+
/// - The vault must have wstETH to withdraw.
|
|
92
|
+
/// - The total amount to withdraw must not be less than the minimum amount per request.
|
|
93
|
+
///
|
|
94
|
+
/// @param vaultId The ID of the vault.
|
|
95
|
+
function requestLidoWithdrawal(uint256 vaultId) external;
|
|
96
|
+
|
|
97
|
+
/// @notice Sets the slippage tolerance for Curve swaps.
|
|
98
|
+
///
|
|
99
|
+
/// @dev Emits a {SetSlippageTolerance} event.
|
|
100
|
+
///
|
|
101
|
+
/// Notes:
|
|
102
|
+
/// - This affects all vaults.
|
|
103
|
+
///
|
|
104
|
+
/// Requirements:
|
|
105
|
+
/// - The caller must be the comptroller.
|
|
106
|
+
/// - `newSlippageTolerance` must not exceed MAX_SLIPPAGE_TOLERANCE.
|
|
107
|
+
///
|
|
108
|
+
/// @param newTolerance The new slippage tolerance as UD60x18.
|
|
109
|
+
function setSlippageTolerance(UD60x18 newTolerance) external;
|
|
110
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// solhint-disable func-name-mixedcase
|
|
3
|
+
pragma solidity >=0.8.22;
|
|
4
|
+
|
|
5
|
+
/// @title ICurveStETHPool
|
|
6
|
+
/// @notice Minimal interface for the Curve stETH/ETH pool.
|
|
7
|
+
/// @dev The pool has two tokens: ETH (index 0) and stETH (index 1).
|
|
8
|
+
interface ICurveStETHPool {
|
|
9
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
10
|
+
READ-ONLY FUNCTIONS
|
|
11
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
12
|
+
|
|
13
|
+
/// @notice Get the amount of output coin for a given input.
|
|
14
|
+
/// @param i The index of the input coin.
|
|
15
|
+
/// @param j The index of the output coin.
|
|
16
|
+
/// @param dx The amount of input coin.
|
|
17
|
+
/// @return dy The expected amount of output coin.
|
|
18
|
+
function get_dy(int128 i, int128 j, uint256 dx) external view returns (uint256 dy);
|
|
19
|
+
|
|
20
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
21
|
+
STATE-CHANGING FUNCTIONS
|
|
22
|
+
//////////////////////////////////////////////////////////////////////////*/
|
|
23
|
+
|
|
24
|
+
/// @notice Exchange between two tokens in the pool.
|
|
25
|
+
/// @param i The index of the input coin (0 = ETH, 1 = stETH).
|
|
26
|
+
/// @param j The index of the output coin (0 = ETH, 1 = stETH).
|
|
27
|
+
/// @param dx The amount of input coin to exchange.
|
|
28
|
+
/// @param minDy The minimum amount of output coin to receive.
|
|
29
|
+
/// @return dy The actual amount of output coin received.
|
|
30
|
+
function exchange(int128 i, int128 j, uint256 dx, uint256 minDy) external payable returns (uint256 dy);
|
|
31
|
+
}
|