IETokenWithWhitelist
Public Functions
whitelist
function whitelist() external view returns (contract ILPWhitelist)
WEToken
Wraps the rebasing EToken into a non-rebasing ERC-4626 vault token with static balances. 1 WEToken (share) is worth 1 eToken at the eToken's initial scale ({ETKLib.SCALE_INITIAL}). As the EToken accrues yield, each WEToken becomes redeemable for more eTokens.
The conversion between eTokens (assets) and WETokens (shares) uses {IEToken-getCurrentScale}:
shares = assets * _shareScale / scale
assets = shares * scale / _shareScale
where _shareScale = SCALE_INITIAL * 10**decimals (computed at construction) normalizes the
share unit so that 1 WEToken = 1 eToken when the eToken has no accrued returns.
If the underlying eToken has a whitelist, this contract's address must be whitelisted.
Variables
WAD
uint256 WAD
SCALE_INITIAL
uint256 SCALE_INITIAL
Initial scale of the underlying eToken (see {ETKLib.SCALE_INITIAL}), in WAD.
_shareScale
uint256 _shareScale
Factor that maps 1 eToken base unit (at the initial scale) to WEToken base units.
SCALE_INITIAL * 10**(WEToken decimals - eToken decimals). For an eToken with 6 decimals
this equals 1e26: at the initial scale, shares = assets * 1e26 / 1e14 = assets * 1e12,
so 1 eToken (1e6) wraps into exactly 1 WEToken (1e18).
freezer
address freezer
Address authorized to call {setFrozen}. If address(0), anyone may call it but the freeze is always validated against the eToken's whitelist (open-freeze / cache mode). Can be changed by the owner via {setFreezer}.
frozen
mapping(address => bool) frozen
Tracks frozen accounts; frozen accounts cannot transfer WETokens out
When the eToken has a whitelist, this acts as a cache of whatever is enabled or not for the eToken. An account can't be frozen unless it can't transfer out normal eTokens (checked from the whitelist), and can't be unfrozen unless it CAN transfer out normal eTokens.
Events
AccountFrozen
event AccountFrozen(address account, bool frozen)
Emitted when an account is frozen or unfrozen
FreezerChanged
event FreezerChanged(address oldFreezer, address newFreezer)
Emitted when the freezer address is changed by the owner
Errors
FrozenAccount
error FrozenAccount(address account)
Thrown when a transfer is attempted from a frozen account
NotFreezer
error NotFreezer()
Thrown when {setFrozen} is called by an unauthorized address (freezer is set and caller is not the freezer)
FrozenStateMismatch
error FrozenStateMismatch(address user, bool whitelistFrozen, bool newFrozenState)
Thrown when the requested frozen state conflicts with the eToken whitelist's sendTransfer decision
NoWhitelistConfigured
error NoWhitelistConfigured()
Thrown when freezer is address(0) and the eToken has no whitelist to validate against
InvalidAssetDecimals
error InvalidAssetDecimals(uint8 decimals)
Thrown when the underlying eToken has more than 18 decimals (can't be represented in the share scale)
Public Functions
constructor
constructor(contract IEToken eToken_, string name_, string symbol_, address freezer_, address owner_) public
Parameters
| Name | Type | Description |
|---|---|---|
| eToken_ | contract IEToken | The underlying rebasing EToken to wrap |
| name_ | string | Name for the wrapped token |
| symbol_ | string | Symbol for the wrapped token |
| freezer_ | address | Initial address authorized to freeze/unfreeze accounts. Use address(0) for open freeze mode (anyone can call, validated against the eToken's whitelist). |
| owner_ | address | Initial owner, authorized to change the freezer via {setFreezer}. |
decimals
function decimals() public pure returns (uint8)
_Decimals are computed by adding the decimal offset on top of the underlying asset's decimals. This "original" value is cached during construction of the vault contract. If this read operation fails (e.g., the asset has not been created yet), a default of 18 is used to represent the underlying asset's decimals.
See {IERC20Metadata-decimals}._
setFreezer
function setFreezer(address newFreezer) external
Updates the authorized freezer address.
Parameters
| Name | Type | Description |
|---|---|---|
| newFreezer | address | The new freezer. Use address(0) to switch to open-freeze / cache mode. |
setFrozen
function setFrozen(address user, bool frozen_) external
Freezes or unfreezes an account.
Caller must be the freezer or, when freezer is address(0), anyone may call. The eToken's whitelist is always consulted when it is configured: freezing requires the whitelist to reject the user's sendTransfer; unfreezing requires it to accept. When there is no whitelist, the call only succeeds if freezer != address(0) (an authorized freezer may act without a whitelist, but open-freeze mode requires one).
Parameters
| Name | Type | Description |
|---|---|---|
| user | address | The account to freeze or unfreeze. |
| frozen_ | bool | True to freeze, false to unfreeze. |
Private Functions
_convertToShares
function _convertToShares(uint256 assets, enum Math.Rounding rounding) internal view returns (uint256)
Uses the eToken scale directly rather than the totalAssets/totalSupply ratio.
_convertToAssets
function _convertToAssets(uint256 shares, enum Math.Rounding rounding) internal view returns (uint256)
Uses the eToken scale directly rather than the totalAssets/totalSupply ratio.
_update
function _update(address from, address to, uint256 value) internal
Blocks any share movement where from is frozen (transfers and burns).
Deposit (mint: from == address(0)) is already gated by the eToken's safeTransferFrom —
a blacklisted user's eToken transfer will revert at the eToken level.
Burns (redeem/withdraw) must also be blocked: ERC-4626 allows an arbitrary receiver,
so a frozen owner could otherwise drain their underlying eTokens to another address.
_setFreezer
function _setFreezer(address newFreezer) internal