Skip to content

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

NameTypeSet by
kDiemkDIEMconstructor
pt721PT721constructor
unstakeQueueDailyUnstakeQueueconstructor

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

  • pt must be an address whose underlying() == address(kDiem).
  • ptShares > 0, beneficiary != 0.
  • Caller must have approved Redeemer for ptShares of pt.
  • Atomic: PT20 pulled in, redeemed for kDIEM, kDIEM burned, request queued.

redeemPT721AndRequestUnstake

  • tokenId must be owned by msg.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, WrongUnderlying

Trust model

Redeemer's powers are limited to:

  1. Pulling PT20/PT721 from msg.sender (with allowance).
  2. Calling pt.redeem() / pt721.redeem() to unwrap.
  3. Calling kDiem.burn(self, amount) — and kDIEM.burn requires from == msg.sender, so Redeemer can only burn its own transient balance.
  4. 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.

Released under the MIT License.