PT721 (contract)
ERC-721 principal token for arbitrary-maturity positions. Singleton — one contract holds all PT721 positions for the Venice path.
contracts/src/platforms/venice/PT721.sol
Inherits
ERC721 (OpenZeppelin), Ownable2Step
Constants
| Name | Value |
|---|---|
ROLE_DELAY | 7 days |
Immutables
| Name | Type |
|---|---|
underlying | address (kDIEM) |
Mutable state
| Name | Purpose |
|---|---|
locker | Sole authorized caller of deposit |
pendingLocker, lockerEffectiveAt | Rotation buffer |
nextTokenId | Monotonically incremented (starts at 1) |
_positions[tokenId] | Position { principal: uint128, maturity: uint64 } |
Wiring setters
function setLockerInitial(address locker_) external onlyOwner;
function proposeLocker(address locker_) external onlyOwner;
function activateLocker() external;
function cancelLockerChange() external onlyOwner;Deposit (mint)
function deposit(uint256 amount, uint64 maturity, address recipient)
external onlyLocker
returns (uint256 tokenId);amount > 0,recipient != 0,maturity > block.timestamp.- Pulls
amountunderlying frommsg.sender. tokenId = nextTokenId++(starts at 1).- Stores
_positions[tokenId] = (uint128(amount), maturity). - Mints
tokenIdtorecipient.
Redeem (burn)
function redeem(uint256 tokenId, address to, address from)
external
returns (uint256 underlyingAmount);from == ownerOf(tokenId)required (WrongOwner).msg.sendermust be owner OR approved fortokenIdOR approved-for-all by owner.block.timestamp >= _positions[tokenId].maturity(NotMatured).- Reads
principal, deletes position, burns NFT, transfersprincipalunderlying toto.
Views
function position(uint256 tokenId)
external view
returns (uint256 principal, uint64 maturity);Plus standard ERC-721 surface: ownerOf, balanceOf, approve, setApprovalForAll, getApproved, isApprovedForAll, transferFrom, safeTransferFrom, name, symbol, tokenURI (default null).
Events
Deposited(tokenId, payer, recipient, principal, maturity)
Redeemed(tokenId, owner, recipient, principal)
LockerActivated, LockerProposed, LockerChangeCancelledErrors
ZeroAmount, ZeroAddress, MaturityInPast, NotMatured,
NotAuthorized, WrongOwner, NotLocker,
AlreadySet, NoPending, TooEarlyPosition encoding
principal is uint128 (≤ 3.4 × 10^38 wei — sufficient for any realistic amount). maturity is uint64 (valid through year ~2554). Both packed into one storage slot.
Locker rotation
Unlike PT20 (which has immutable locker per-deploy), PT721's locker is mutable and singleton. Rotation via 7-day timelock affects all subsequent mints. Existing positions are unaffected (only their original owner can transfer, and only after-maturity redemption is needed to unwrap).
safeMint vs _mint
PT721 uses _mint (not _safeMint). Rationale: _safeMint calls onERC721Received on the recipient, allowing a receiver contract to revert and grief the Locker. Since this NFT is created by Locker as part of an atomic lockPT721, we don't want any external callback to be able to abort the whole transaction.
If the recipient is a contract that can't handle ERC-721, the position is still mintable but the owner contract just can't transferFrom it via safe paths. Owner can always burn-and-redeem at maturity.
No tokenURI / metadata
Default ERC-721 returns empty tokenURI. NFT marketplaces can read position(tokenId) directly for (principal, maturity) display. A future metadata service (on-chain SVG, off-chain JSON) can be wired without breaking the standard interface.