Omniscia Platypus Finance Audit

VePtp Static Analysis Findings

VePtp Static Analysis Findings

VPP-01S: Inexistent Protection Against Reentrancy

TypeSeverityLocation
Language SpecificMinorVePtp.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:

contracts/VePtp.sol
252/// @notice This function is called when users stake NFTs
253/// When Platypus NFT sent via safeTransferFrom(), we regard this action as staking the NFT
254/// Note that transferFrom() is ignored by this function
255function onERC721Received(
256 address _operator,
257 address _from,
258 uint256 _tokenId,
259 bytes calldata data
260) 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 first
265 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 nft
277function unstakeNft() external nonReentrant {
278 _unstakeNft(msg.sender);
279}
280
281/// @notice private function used to unstake nft
282/// @param _addr the address of the nft owner
283function _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

TypeSeverityLocation
Gas OptimizationInformationalVePtp.sol:L256, L259

Description:

The linked input variables remain unutilized in the function.

Example:

contracts/VePtp.sol
255function onERC721Received(
256 address _operator,
257 address _from,
258 uint256 _tokenId,
259 bytes calldata data
260) 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 first
265 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.