Redeemer
User-facing exit point. Pulls PT20 or PT721, burns kDIEM, queues unstake request.
contracts/src/platforms/venice/Redeemer.sol
Inherits
Ownable2Step, ReentrancyGuard, Pausable
Immutables
| Name | Type | Set by |
|---|---|---|
kDiem | kDIEM | constructor |
pt721 | PT721 | constructor |
unstakeQueue | DailyUnstakeQueue | constructor |
All three are immutable. There are no rotation paths inside Redeemer — to swap Redeemer, deploy a new one and rotate kDIEM.isRedeemer allowlist and Queue.redeemer (each through their own 7-day timelock).
User functions
solidity
function redeemAndRequestUnstake(address pt, uint256 ptShares, address beneficiary)
external nonReentrant whenNotPaused
returns (uint64 requestDay);
function redeemPT721AndRequestUnstake(uint256 tokenId, address beneficiary)
external nonReentrant whenNotPaused
returns (uint64 requestDay, uint256 principal);redeemAndRequestUnstake
ptmust be an address whoseunderlying() == address(kDiem).ptShares > 0,beneficiary != 0.- Caller must have approved
RedeemerforptSharesofpt. - Atomic: PT20 pulled in, redeemed for kDIEM, kDIEM burned, request queued.
redeemPT721AndRequestUnstake
tokenIdmust be owned bymsg.sender(and Redeemer must be approved).- Atomic: NFT pulled in, redeemed for kDIEM, kDIEM burned, request queued.
- Returns the
principal(amount of DIEM) tied to that NFT.
Admin functions
solidity
function pause() external onlyOwner;
function unpause() external onlyOwner;No setters — wiring is immutable for life of the contract.
Events
solidity
event RedeemedAndRequested(address indexed payer, address indexed beneficiary,
address indexed pt, uint256 ptShares, uint256 kDiemRedeemed, uint64 requestDay);
event PT721RedeemedAndRequested(address indexed payer, address indexed beneficiary,
uint256 indexed tokenId, uint256 kDiemRedeemed, uint64 requestDay);Errors
ZeroAddress, ZeroAmount, WrongUnderlyingTrust model
Redeemer's powers are limited to:
- Pulling PT20/PT721 from
msg.sender(with allowance). - Calling
pt.redeem()/pt721.redeem()to unwrap. - Calling
kDiem.burn(self, amount)— andkDIEM.burnrequiresfrom == msg.sender, so Redeemer can only burn its own transient balance. - Calling
queue.requestUnstake(amount, beneficiary).
A hostile Redeemer (if somehow added to kDIEM.isRedeemer and Queue.redeemer) would still need to source kDIEM honestly because of the self-burn constraint. The 7-day timelock on both kDIEM and Queue rotations gives users time to exit if a malicious Redeemer is being added.