20 写了一个简单的挖矿合约,里面有一些问题,希望大佬们能帮忙瞅瞅

先简述一下问题: 1:部署的时候是用小狐狸部署的然后部署在ETH链下,现在账号里面测试ETH币还有不少,但是在调用ownerTransfer转账的时候执行 to.transfer(withdrawAmount/10000);这一行就会出问题,去掉这一行就没问题,那位大佬帮忙看看原因

2:userTransfer函数中如何给用户自己给自己提币 ownerTransfer 函数中合约拥有者如何给矿工转账,用来结算奖励

3:现阶段是部署在ETH下,但是后续会部署在其他ERC20的链上(自己发的链和币),给矿工结算奖励的时候应该如何结算,现有合约代码需要做什么改变

4:因为头一次写挖矿合约,所以未引入其他的合约,是否需要引入一些其他合约用来保证安全性

改挖矿合约和现有市面上的流动性质押挖矿有区别,只是单纯的通过挖矿速度计算矿工奖励,然后通过合约拥有者给矿工结算奖励 其中如果有什么问题,望各位大佬能指点一下

合约代码如下:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract MiningContract {
  //合约拥有者
  address private owner;
  //合约解锁时间
  uint256 private lockoutTime;
  // 挖矿速度,每秒钟一个币
  uint256 constant miningSpeed = 1; 

   //用户信息体
   struct UserInfo {
     uint256 totalCumulative;//恒定总累积量
     uint256 totalReward; //累积奖励
     uint256 userSpeed;   //速度
     uint256 startTime;   //当前速度的挖矿开始时间
   }
   //用户信息体 = 地址 对应 用户信息体
   mapping(address => UserInfo) private userInfo;
   address[] private addressList;

   //构造方法,部署的时候给合约拥有者赋值
    constructor()  payable {
        owner = msg.sender;
    }

   event userLog(uint256 blockTime ,uint256 lockoutTime ,UserInfo userInfo);
   event lockoutLog(string message, address[] addressList, uint256 timeDiff, uint256 lastReward);
   event ownerTransferLog(address formAddress,uint256 withdrawAmount);

    //挖矿函数
    function strat(address user, uint256 speed) external {
      require(msg.sender == owner, "Only owner can call this function");
      require(lockoutTime == 0 ,"locked warehouse");//判断是否锁仓,未锁仓,才能挖矿
      UserInfo storage info = userInfo[user];
      addressList.push(user);//定义一个addressList用来存储用户信息地址,以便在后续中锁仓时使用
      if (info.startTime == 0) {
        info.startTime = block.timestamp;
      }else{
        uint256 timeDiff = block.timestamp - info.startTime;
       if(timeDiff > 24*60*60){
            uint256 lastReward = info.userSpeed * 24*60*60 * getRatio();
            info.totalReward += lastReward;
            info.startTime = block.timestamp;
       }else{
            uint256 lastReward = info.userSpeed * timeDiff * getRatio();
            info.totalReward += lastReward;
            info.startTime = block.timestamp;
       }
      }
      info.userSpeed = speed;
      emit userLog(block.timestamp , lockoutTime , info);
  }

    //锁仓函数
    function lockout() external {
        require(msg.sender == owner, "Only owner can call this function");
        lockoutTime = block.timestamp;
         for (uint256 i = 0; i < addressList.length; i++) {
            address userAddress = addressList[i];
            UserInfo storage info = userInfo[userAddress]; //声明一个UserInfo类型的变量info,将userInfo[users[i]]赋值给它
            uint256 lastReward = 0;                        //声明一个uint256类型的变量lastReward,初始值为0
            if (info.userSpeed != 0) {                     //如果info.userSpeed不等于0
                uint256 timeDiff = lockoutTime - info.startTime; //计算时间差
            if (timeDiff >= 24*60*60) {                    //如果时间差大于等于1天
                lastReward = info.userSpeed * 24*60*60 * getRatio(); //计算上一次奖励的数量
            } else {
                lastReward = info.userSpeed * timeDiff * getRatio(); //计算上一次奖励的数量
             }
             emit lockoutLog("lockout Log Value is", addressList, timeDiff, lastReward);
            }
             info.totalCumulative = info.totalReward + lastReward;  //将总累计奖励赋值给info.totalCumulative
            }
             // totalCumulative = getTotalCumulative(); //将所有用户的总累计奖励赋值给totalCumulative
  }

    //声明一个函数userTransfer
    function userTransfer() external payable { 
          require(lockoutTime > 0 ,"Unlocked warehouse");//判断是否锁仓,已锁仓,才能提币
          UserInfo storage info = userInfo[msg.sender]; //声明一个UserInfo类型的变量info,将userInfo[msg.sender]赋值给它
          uint256 percentage = withdraw();
          uint256 withdrawAmount = info.totalCumulative * percentage/100 - (info.totalCumulative - info.totalReward); // 提币额度,其中totalReward为累计奖励数
          require(msg.value <= withdrawAmount, "Insufficient mining fee");//这一步判定暂定,看看有无必要加上
          info.totalReward -= withdrawAmount;//将转账金额从info.totalCumulative中减去
          payable(msg.sender).transfer(withdrawAmount);//将转账金额转账给to地址
  }

    //声明一个函数ownerTransfer,只有owner才能调用
    function ownerTransfer(address payable to) external payable{
          require(msg.sender == owner, "Only owner can call this function");//要求只有owner才能调用该函数
          // require(lockoutTime > 0 ,"Unlocked warehouse");//判断是否锁仓,已锁仓,才能提币
          UserInfo storage info = userInfo[to];
          uint256 percentage = withdraw();
          uint256 withdrawAmount = info.totalCumulative * percentage/100 - (info.totalCumulative - info.totalReward); // 提币额度,其中totalReward为累计奖励数
          require(msg.value <= withdrawAmount, "Insufficient mining fee");//要求支付的以太币数量大于等于转账金额
          info.totalReward -= withdrawAmount;//将转账金额从totalCumulative中减去
          to.transfer(withdrawAmount/10000);
          emit ownerTransferLog(to, withdrawAmount);
}

    //锁仓后提币时,计算截止到今天的可提币比例
    function withdraw() internal view returns (uint256) {
        uint256 daysPassed = (block.timestamp - lockoutTime) / 86400; // 计算当前是第几天,86400为一天的秒数
        uint256 withdrawPercentage = 0;
        if (daysPassed == 0) {
            withdrawPercentage = 5; // 第一天提币比例为5%
        } else {
            withdrawPercentage = 3; // 第二天及以后提币比例为3%
            for (uint i = 1; i < daysPassed; i++) {
                withdrawPercentage += 3; // 每过一天提币比例增加3%
            }
        }
        return withdrawPercentage; // 当前可提币比例
    }

    //声明一个函数amount,获取用户的累计奖励
    function userAmount(address user) external view returns (uint256) {
          UserInfo storage info = userInfo[user];//声明一个UserInfo类型的变量info,将userInfo[user]赋值给它
          uint256 userLastReward = 0;//声明一个uint256类型的变量lastReward,初始值为0,用来获取用户在当前速度下的累计奖励量
          uint256 timeDiff = block.timestamp - info.startTime;
          if(timeDiff > 24*60*60){
             userLastReward = info.userSpeed * 24*60*60 * getRatio();
          }else{
             userLastReward = info.userSpeed * timeDiff * getRatio();
          }
        return info.totalReward + userLastReward;//返回总累计奖励加上上一次奖励的数量
    }

    //声明一个私有函数getRatio,获取基础挖矿速度的奖励
    function getRatio() private pure returns (uint256) {
        return miningSpeed;
  }

    //声明一个函数speed,获取当前用户的挖矿速度
    function userSpeed(address user) external view returns (uint256) {
       return userInfo[user].userSpeed;//返回用户的速度
  }

    //声明一个函数residueTime,获取当前用户的剩余挖矿时间
    function residueTime(address user) external view returns (uint256) {
       uint256 timeDiff = block.timestamp - userInfo[user].startTime;
       if (timeDiff >= 24*60*60) {     //如果时间差大于等于1天
           return 0;  
       } else {
           return 24*60*60 - timeDiff;   //返回剩余时间
       }

  }

      //声明一个函数residueTime,获取当前用户的剩余挖矿时间
    function getBlockTime() external view returns (uint256) {
       return block.timestamp;  
  }
}
请先 登录 后评论

最佳答案 2023-06-30 09:46

  1. to.transfer(withdrawAmount/10000); 出问题,一般有这两个可能性:

    1. 当前合约里没有足够的ETH
    2. to 是一个合约, transfer 只是用2300 gas, 不够执行合约的Receive 函数
  2. 部署在其他EVM 链上(没有 ERC20的链 这个说法) 通常不需要修改代码, 如果有第三方合约地址依赖的话,修改一下地址就可以。

  3. 要不要引入其他的合约, 这个要看你的逻辑,不是必须的。

请先 登录 后评论

其它 1 个回答

0527
请先 登录 后评论
  • 2 关注
  • 0 收藏,1838 浏览
  • 醒梦无痕 提出于 2023-06-28 11:46