This contract is responsible for managing tokenized asset balances. It makes sure that the balance of tokenised assets is always valid and provides a way to recover from an invalid tokenised balance in case of a .
2. Contract details
TokenizedAssetManager.sol is written in Solidity version 0.8.15
Features
Keeping track of the tokenized asset balances
Provides a check for sufficient tokenised balance
Implements recovery functions to recover from the stalking attack
Functions
hasSufficientTokenizedBalance
Overview
A function to check the tokenised balance for the provided address is valid.
This function takes one argument supplied by the caller:
An internal function called by the ATR Module when burning an ATR Token. It removes the asset corresponding to the supplied ATR Token ID from the asset mapping (ATR Token ID => Asset).
This function takes one argument supplied by the ATR Module:
A function that checks the state is actually invalid and stores an on-chain report, that is used in the second step of the recovery process.
The reason to divide the recovery process into two transactions is to get rid of the otherwise possible reentrancy exploits. One could possibly transfer a tokenized asset from a PWN Safe and, before tokenized balance check can happen, call the recover function, which would recover the PWN Safe from that transitory invalid state and tokenized balance check would pass, effectively bypassing the transfer rights rules.
This function takes one argument supplied by the PWN Safe being recovered:
uint256atrTokenId - ID of the invalid ATR Token
addressowner - Address of the ATR tokens owner
Implementation
function reportInvalidTokenizedBalance(
uint256 atrTokenId,
address owner
) external {
// Check if atr token is in owners safe
// That would also check for non-existing ATR tokens
require(
tokenizedAssetsInSafe[owner].contains(atrTokenId),
"Asset is not in callers safe"
);
// Check if state is really invalid
MultiToken.Asset memory asset = assets[atrTokenId];
(, uint256 tokenizedBalance) = tokenizedBalances[owner][
asset.assetAddress
].tryGet(asset.id);
require(
asset.balanceOf(owner) < tokenizedBalance,
"Tokenized balance is not invalid"
);
// Store report
invalidTokenizedBalanceReports[owner] = InvalidTokenizedBalanceReport(
atrTokenId,
block.number
);
}
The primary reason for marking the ATR token as invalid rather than burning it is to prevent other DeFi protocols from unexpected behaviour in case the ATR token is used in them.
This function does not define any parameters and has to be called by the PWN Safe being recovered.
Implementation
function recoverInvalidTokenizedBalance() external {
address owner = msg.sender;
InvalidTokenizedBalanceReport
memory report = invalidTokenizedBalanceReports[owner];
uint256 atrTokenId = report.atrTokenId;
// Check that report exist
require(report.block > 0, "No reported invalid tokenized balance");
// Check that report was posted in different block than recover call
require(
report.block < block.number,
"Report block number has to be smaller then current block number"
);
// Decrease tokenized balance (would fail for invalid ATR token)
MultiToken.Asset memory asset = assets[atrTokenId];
require(
_decreaseTokenizedBalance(atrTokenId, owner, asset),
"Asset is not in callers safe"
);
delete invalidTokenizedBalanceReports[owner];
emit TransferViaATR(owner, address(0), atrTokenId, asset);
// Mark atr token as invalid (tokens asset holder is lost)
isInvalid[atrTokenId] = true;
}
View Functions
getAsset
Overview
This function takes one argument supplied by the caller:
This event is emitted when a tokenised asset is transferred.
This event defines four parameters:
address indexedfrom - Address from which was the token transferred
address indexedto - Address to which was the token transferred
uint256 indexedatrTokenId - ID of the transferred token
MultiToken.Asset memoryasset - An asset struct (see )
MultiToken.Asset memoryasset - An asset struct (see )
Recovery functions to recover from
This should not be necessary, thanks to the , but if you ever give permission to a malicious actor and you are a victim of this attack, please contact the PWN Team on .
This function expects that the user called function in some previous block. In the end, it will recover the PWN Safe from an invalid tokenized balance caused by the reported ATR Token and mark that token as invalid.
Returns the asset struct (see ) corresponding to the supplied ATR Token ID.
MultiToken.Asset memoryasset - An asset struct (see )