[MEDIUM] Potential reentrancy risk

The safeMint function updates the _setTokenData internal state after calling _safeMint, which may be at risk of a reentrancy attack. For example, due to the callback function in _safeMint, an attacker could execute the safeMint function again within the callback function, setting the same value for different tokenids.

try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
totalSupply += _amount;
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(msg.sender, tokenId);
_setTokenData(tokenId, value);

Recommendation

_setTokenData(tokenId, value);
_safeMint(msg.sender, tokenId);

[Low] Extra stakingToken cannot be removed

If someone inadvertently sends ERC20 tokens directly to the contract (rather than through the contract's staking function), these tokens will not be recorded in the contract's totalSupply. The withdrawAll function only determines the amount of tokens that can be withdrawn based on totalSupply. This means that if additional tokens are sent to the contract but are not recorded through the safeMint or stakingMore function, these tokens will not be included in totalSupply.

function withdrawAll(address to) external onlyOwner {
    require(finishAt<block.timestamp,"staking not finish yet");
    require(totalSupply > 0, "totalSupply = 0");
    stakingToken.transfer(to , totalSupply);
    totalSupply =0;
}

Recommendation

Add a function to report the current ERC20 token balance of the contract, and compare it with totalSupply to help identify and manage inconsistencies.

[INFO] ERC20 interface is not correct

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external;
    function allowance(address owner, address spender)
        external
        view

Due to the lack of return value, non-standard ERC20 interfaces may stop interacting with contracts compiled with Solidity > 0.4.22.

The correct transfer interface is as follows:

function transfer(address to, uint256 amount) external returns (bool);

Recommendation

Set appropriate return values and types for the defined ERC20 functions.

[INFO] stakingToken with fee-on-transfer is not supported

The staking token may transfer less token to the contract if it takes fee on transfer, causing bad balance sheet.