每次都需要声明恢复事务

提问

奇怪的事情正在发生。我正在测试一些关于重新混合EVM的合同。我有一些非常基本的NFT的订单,在交易中很好,当你要做的时候,我有一个很好的合同。然而,如果我试图执行unposition函数,事务就会被返回,称需要的条件不会通过。然而更奇怪的是,如果我把要求分别调用在需要的情况下,情况是正确的! 我不知道在这一点上发生了什么,所以请提供任何建议或帮助。目前我有三份合同(ERC721 ERC721),所有的功能都在正常工作,除了无桩功能。 这些是我的合同: 能量。sol(ERC20): 燃料。sol(ERC721) 发电机。sol(stunk): 如果您想测试流(我希望您做),一定要首先部署燃料和能量合同,然后在部署生成器合同时使用契约的地址作为构造函数参数。然后在燃料实例中批准所有的发电机地址,在发电机合同中提出一些nfts的股份,并试图获得股份。每个函数都很好,但是无桩功能。 再次感谢你的帮助! 函数ownedby这需要从你的燃料合同中获取(fuelId)的地址,但在你在发电机中标记你的NFT之后。现在是发电机。sol是这个NFT的所有者,你需要的函数ownedby这是不工作的。此外,我还添加了(删除[fuelId];)到您的索赔函数的底部。在脱下你的nft之前,不要忘记使用关于发电机地址的AddMinter funtion。sol合同。希望我是有用的。 下面更新的代码

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/* Simple ERC20 token contract to issue rewards */
contract Energy is ERC20, Ownable {
    mapping(address => bool) minters;
    constructor() ERC20("ENERGY", "NRG") {
        _mint(msg.sender, 100 * 10**decimals());
    }
    modifier isMinter() {
        require(minters[msg.sender], "Caller is not authorized to mint!");
        _;
    }
    function mintRewards(address to, uint256 amount) external isMinter {
        _mint(to, amount * 10**decimals());
    }
    function addMinter(address account) public onlyOwner {
        minters[account] = true;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract Fuel is ERC721, ERC721Burnable, Ownable {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIdCounter;
    constructor() ERC721("Fuel", "FUEL") {}
    function safeMint(address to) public onlyOwner {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./Energy.sol";
import "./Fuel.sol";
struct Loader {
    uint256[] fuelIds;
    mapping(uint256 => uint256) loadBlock;
}
contract Generator is Ownable, ReentrancyGuard, IERC721Receiver {
    Fuel fuel;
    Energy energy;
    uint256 rewardsPerBlock = 5;
    mapping(address => Loader) loaders;
    // Enumeration of fuelIds staked indexes of a loader
    mapping(address => mapping(uint256 => uint256)) public fuelIdIndex;
    // tracks owner of a fuelId
    mapping(uint256 => address) public loaderOf;
    constructor(address _fuel, address _energy) {
        fuel = Fuel(_fuel);
        energy = Energy(_energy);
    }
    function stake(uint256 fuelId) public nonReentrant {
        // safe checks
        require(
            fuel.ownerOf(fuelId) == msg.sender,
            "You're not the owner of this NFT"
        );
        // push new token to staking collection
        loaders[msg.sender].fuelIds.push(fuelId);
        // updates index reference of fuelId
        uint256 totalFuel = loaders[msg.sender].fuelIds.length;
        fuelIdIndex[msg.sender][fuelId] = totalFuel - 1;
        // inits staking block
        loaders[msg.sender].loadBlock[fuelId] = block.number;
        // add it to reference
        loaderOf[fuelId] = msg.sender;
        fuel.safeTransferFrom(address(msg.sender), address(this), fuelId);
    }
    function unstake(uint256 fuelId) public nonReentrant {
        // safe checks
        require(ownedByThis(fuelId), "This fuel is not being loaded here!");
        require(
            _loaderOf(fuelId) == address(msg.sender),
            "You haven't loaded this fuel here!"
        );
        uint256 lastFuelIndex = loaders[msg.sender].fuelIds.length - 1;
        uint256 fuelIndex = fuelIdIndex[msg.sender][fuelId];
        // swap current fuelId to last position
        if (lastFuelIndex != fuelIndex) {
            uint256 lastFuelId = loaders[msg.sender].fuelIds[lastFuelIndex];
            loaders[msg.sender].fuelIds[fuelIndex] = lastFuelIndex; // Move the last token to the slot of the to-delete token
            fuelIdIndex[msg.sender][lastFuelId] = fuelIndex; // Update the moved token's index
        }
        // remove the last element from mapping and array
        delete fuelIdIndex[msg.sender][fuelId];
        delete loaders[msg.sender].fuelIds[lastFuelIndex];
        delete loaders[msg.sender].loadBlock[fuelId];
        delete loaderOf[fuelId];
        // Transfer back to the owner
        fuel.safeTransferFrom(address(this), address(msg.sender), fuelId);
        claim(fuelId);
    }
    function claim(uint256 fuelId) public {
        // safe checks
        require(ownedByThis(fuelId), "This fuel is not being loaded here!");
        require(
            _loaderOf(fuelId) == address(msg.sender),
            "You haven't loaded this fuel here!"
        );
        uint256 rewardsToClaim = getPendingRewards(msg.sender, fuelId);
        energy.mintRewards(msg.sender, rewardsToClaim);
        loaders[msg.sender].loadBlock[fuelId] = block.number;
    }
    function claimAll() public nonReentrant {
        // safe checks
        require(
            loaders[msg.sender].fuelIds.length > 0,
            "You have no fuel loaded here!"
        );
        uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
        for (uint256 i = 0; i < totalFuelLoaded; i++) {
            uint256 fuelId = loaders[msg.sender].fuelIds[i];
            claim(fuelId);
        }
    }
    function getPendingRewards(address account, uint256 fuelId)
        public
        view
        returns (uint256)
    {
        uint256 loadBlock = loaders[account].loadBlock[fuelId];
        uint256 blocksElapsed = block.number - loadBlock;
        return blocksElapsed * rewardsPerBlock;
    }
    function getAllPendingRewards() public view returns (uint256) {
        uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
        uint256 totalRewards = 0;
        for (uint256 i = 0; i < totalFuelLoaded; i++) {
            uint256 fuelId = loaders[msg.sender].fuelIds[i];
            totalRewards += getPendingRewards(msg.sender, fuelId);
        }
        return totalRewards;
    }
    function _loaderOf(uint256 fuelId) public view returns (address) {
        return loaderOf[fuelId];
    }
    function totalFuelLoadedBy(address account) public view returns (uint256) {
        return loaders[account].fuelIds.length;
    }
    function generatorAddress() public view returns (address) {
        return address(this);
    }
    function ownedByThis(uint256 fuelId) public view returns (bool) {
        return address(fuel.ownerOf(fuelId)) == address(this);
    }
    function onERC721Received(
        address operator,
        address from,
        uint256 fuelId,
        bytes calldata data
    ) external override returns (bytes4) {
        return this.onERC721Received.selector;
    }
}

回答

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import "./Energy.sol";
import "./Fuel.sol";
contract Generator is Ownable, ReentrancyGuard, ERC721Holder {
Fuel fuel;
Energy energy;
struct Loader {
uint256[] fuelIds;
mapping(uint256 => uint256) loadBlock;
}
uint256 rewardsPerBlock = 5;
mapping(address => Loader) loaders;
// Enumeration of fuelIds staked indexes of a loader
mapping(address => mapping(uint256 => uint256)) public fuelIdIndex;
// tracks owner of a fuelId
mapping(uint256 => address) public loaderOf;
constructor(address _fuel, address _energy) {
    fuel = Fuel(_fuel);
    energy = Energy(_energy);
}
function stake(uint256 fuelId) public nonReentrant {
    // safe checks
    require(
        fuel.ownerOf(fuelId) == msg.sender,
        "You're not the owner of this NFT"
    );
    // push new token to staking collection
    loaders[msg.sender].fuelIds.push(fuelId);
    // updates index reference of fuelId
    uint256 totalFuel = loaders[msg.sender].fuelIds.length;
    fuelIdIndex[msg.sender][fuelId] = totalFuel - 1;
    // inits staking block
    loaders[msg.sender].loadBlock[fuelId] = block.number;
    // add it to reference
    loaderOf[fuelId] = msg.sender;
    fuel.safeTransferFrom(address(msg.sender), address(this), fuelId);
}
function unstake(uint256 fuelId) public nonReentrant {
    // safe checks
    require(msg.sender == loaderOf[fuelId], "You are not the owner"); 
//require(ownedByThis(fuelId), "This fuel is not being loaded here!");
    // require(
    //     _loaderOf(fuelId) == address(msg.sender),
    //     "You haven't loaded this fuel here!"
    // );
    uint256 lastFuelIndex = loaders[msg.sender].fuelIds.length - 1;
    uint256 fuelIndex = fuelIdIndex[msg.sender][fuelId];
    // swap current fuelId to last position
    if (lastFuelIndex != fuelIndex) {
        uint256 lastFuelId = loaders[msg.sender].fuelIds[lastFuelIndex];
        loaders[msg.sender].fuelIds[fuelIndex] = lastFuelIndex; // Move the 
 last token to the slot of the to-delete token
        fuelIdIndex[msg.sender][lastFuelId] = fuelIndex; // Update the 
 moved token's index
    }
    // remove the last element from mapping and array
    delete fuelIdIndex[msg.sender][fuelId];
    delete loaders[msg.sender].fuelIds[lastFuelIndex];
    delete loaders[msg.sender].loadBlock[fuelId];
    // Transfer back to the owner
    fuel.safeTransferFrom(address(this), address(msg.sender), fuelId);
    claim(fuelId);
}
function claim(uint256 fuelId) public {
    // safe checks
    //require(ownedByThis(fuelId), "This fuel is not being loaded here!");
    require(msg.sender == loaderOf[fuelId], "You are not the owner");
    // require(
    //     _loaderOf(fuelId) == address(msg.sender),
    //     "You haven't loaded this fuel here!"
    // );
    uint256 rewardsToClaim = getPendingRewards(msg.sender, fuelId);
    energy.mintRewards(msg.sender, rewardsToClaim);
    loaders[msg.sender].loadBlock[fuelId] = block.number;
    delete loaderOf[fuelId];
}
function claimAll() public nonReentrant {
    // safe checks
    require(
        loaders[msg.sender].fuelIds.length > 0,
        "You have no fuel loaded here!"
    );
    uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
    for (uint256 i = 0; i < totalFuelLoaded; i++) {
        uint256 fuelId = loaders[msg.sender].fuelIds[i];
        claim(fuelId);
    }
}
function getPendingRewards(address account, uint256 fuelId) public view 
returns (uint256) {
    uint256 loadBlock = loaders[account].loadBlock[fuelId];
    uint256 blocksElapsed = block.number - loadBlock;
    return blocksElapsed * rewardsPerBlock;
}
function getAllPendingRewards() public view returns (uint256) {
    uint256 totalFuelLoaded = totalFuelLoadedBy(msg.sender);
    uint256 totalRewards = 0;
    for (uint256 i = 0; i < totalFuelLoaded; i++) {
        uint256 fuelId = loaders[msg.sender].fuelIds[i];
        totalRewards += getPendingRewards(msg.sender, fuelId);
    }
    return totalRewards;
}
function _loaderOf(uint256 fuelId) public view returns (address) {
    return loaderOf[fuelId];
}
function totalFuelLoadedBy(address account) public view returns (uint256) {
    return loaders[account].fuelIds.length;
}
function generatorAddress() public view returns (address) {
    return address(this);
}
// function ownedByThis(uint256 fuelId) public view returns (bool) {           
//     return address(fuel.ownerOf(fuelId)) == address(this);
// }
function onERC721Received(address, address, uint256, bytes memory) public 
virtual override returns (bytes4) {
    return this.onERC721Received.selector;
}
}

▼版权说明

相关文章也很精彩
推荐内容
更多标签
相关热门
全站排行
随便看看

错说cuoshuo.com——程序员的报错记录

部分内容根据CC版权协议转载,如果您希望取消转载请发送邮件到cuoshuo8@163.com

辽ICP备19011660号-5