Omniscia Platypus Finance Audit
VePtp Static Analysis Findings
VePtp Static Analysis Findings
VPP-01S: Inexistent Protection Against Reentrancy
Type | Severity | Location |
---|---|---|
Language Specific | Minor | VePtp.sol:L255-L260 |
Description:
The onERC721Received
hook has no protection against a re-entrancy attack. While it does not cause a vulnerability to arise, it allows a user to re-send an NFT to the VePtp
over and over which may be considered undesired behaviour and will result in incorrect events being emitted.
Example:
252/// @notice This function is called when users stake NFTs253/// When Platypus NFT sent via safeTransferFrom(), we regard this action as staking the NFT254/// Note that transferFrom() is ignored by this function255function onERC721Received(256 address _operator,257 address _from,258 uint256 _tokenId,259 bytes calldata data260) external returns (bytes4) {261 require(msg.sender == address(nft), 'only platypus NFT can be received');262 require(isUser(_from), 'user has no stake');263
264 // User has previously staked some NFT, try to unstake it first265 if (users[_from].stakedNftId != 0) {266 _unstakeNft(_from);267 }268
269 users[_from].stakedNftId = _tokenId;270
271 emit StakedNft(_from, _tokenId);272
273 return ERC721_RECEIVED;274}275
276/// @notice unstakes current user nft277function unstakeNft() external nonReentrant {278 _unstakeNft(msg.sender);279}280
281/// @notice private function used to unstake nft282/// @param _addr the address of the nft owner283function _unstakeNft(address _addr) private {284 uint256 nftId = users[_addr].stakedNftId;285 require(nftId != 0, 'No NFT is staked');286
287 nft.safeTransferFrom(address(this), _addr, nftId, '');288
289 users[_addr].stakedNftId = 0;290 emit UnstakedNft(_addr, nftId);291}
Recommendation:
We advise the nonReentrant
flag to be introduced to the function as the NFT component of the system appears to be utilized by off-chain code.
Alleviation:
The nonReentrant
modifier was properly introduced to the onERC721Received
callback function, thereby alleviating this exhibit.
VPP-02S: Unused Function Inputs
Type | Severity | Location |
---|---|---|
Gas Optimization | Informational | VePtp.sol:L256, L259 |
Description:
The linked input variables remain unutilized in the function.
Example:
255function onERC721Received(256 address _operator,257 address _from,258 uint256 _tokenId,259 bytes calldata data260) external returns (bytes4) {261 require(msg.sender == address(nft), 'only platypus NFT can be received');262 require(isUser(_from), 'user has no stake');263
264 // User has previously staked some NFT, try to unstake it first265 if (users[_from].stakedNftId != 0) {266 _unstakeNft(_from);267 }268
269 users[_from].stakedNftId = _tokenId;270
271 emit StakedNft(_from, _tokenId);272
273 return ERC721_RECEIVED;274}
Recommendation:
We advise their name to be omitted as the function will still comply to the relevant interface but will not reserve redundant space for the variables.
Alleviation:
The function arguments were properly un-named, silencing the compiler warning.