Solidity

使用 Safemath 子並添加

  • November 22, 2021

好吧,我正在創建一份合約作為我的 ICO,但我在使用 SafeMath 庫時遇到了一個“簡單”的問題。

問題是什麼?我需要將我的代幣購買限制為最多“5 ether(bnb)”,因此我創建了一個名為“investorBalances”的變數,用於保存購買的金額。

完成後,我檢查了我的程式碼,確認投資者購買的金額不高於限額。但隨後發生錯誤,它返回我的“恢復”消息,說它已經達到了限制,但是,這是第一次購買……

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract SALES is Ownable {
 using SafeMath for uint256;
 
 IERC20 token;

 uint256 private rate = 3000; // Number of tokens per BNB  
 uint256 private start = 1636914760; // 16/11/2021
 uint256 private dayMax = 45; // 45 Day
 uint256 private buyMax = 5; //5 bnb
 
 uint256 public initialTokens; // Initial number of tokens available
 bool public initialized = false;
 uint256 public raisedAmount = 0;

 mapping(address => uint256) investorBalances;

 /**
  * BoughtTokens
  * @dev Log tokens bought onto the blockchain
  */
 event BoughtTokens(address indexed to, uint256 value);

 constructor(address _token){
   setAddrERC20(_token);
 }

 /**
  * @dev Fallback function if ether is sent to address insted of buyTokens function
  **/
 receive() external payable {
   buyTokens();
 }

  /**
  * buyTokens
  * @dev function that sells available tokens
  **/
 function buyTokens() public payable whenSaleIsActive {
   uint256 weiAmount = msg.value; // Calculate tokens to sell
   uint256 tokens = weiAmount.mul(rate);
   uint256 amountMax = investorBalances[msg.sender].add(weiAmount);

   if(amountMax >= buyMax){
     revert("You have reached the purchase limit");
   }

   emit BoughtTokens(msg.sender, tokens); // log event onto the blockchain
   raisedAmount = raisedAmount.add(msg.value); // Increment raised amount
   token.transfer(msg.sender, tokens); // Send tokens to buyer
   
   investorBalances[msg.sender] = amountMax;

   payable(owner()).transfer(msg.value);// Send money to owner
 }

 /**
  * whenSaleIsActive
  * @dev ensures that the contract is still active
  **/
 modifier whenSaleIsActive() {
   // Check if sale is active
   assert(isActive());
   _;
 }

 function isActive() public view returns (bool) {
   return (
       initialized == true &&
       block.timestamp >= start && // Must be after the START date
       block.timestamp <= start.add(dayMax * 1 days)// Must be before the end date        
   );
 }

 /**
  * terminate
  * @notice Terminate contract and refund to owner
  **/
 function terminateSales() public onlyOwner  {
   // Transfer tokens back to owner    
   uint256 balance = token.balanceOf(address(this));
   assert(balance > 0);
   token.transfer(owner(), balance);    
 }

 /**
  * tokensAvailable
  * @dev returns the number of tokens allocated to this contract
  **/
 function tokensAvailable() public view returns (uint256) {
   return token.balanceOf(address(this));
 }

 /**
  * investorBalanceAvailable
  * @dev returns the number of tokens the investor bought
  **/
 function investorBalanceAvailable(address _investor) public view returns (uint256) {
   return investorBalances[_investor];
 }

 /**
  * initialize
  * @dev Initialize the contract
  **/
 function initialize() public onlyOwner {
     require(initialized == false); // Can only be initialized once      
     initialized = true;
 }

 function setRate(uint _rate) public onlyOwner{
   rate = _rate;
 }

 function setBuyMax(uint _buyMax) public onlyOwner{
   buyMax = _buyMax;
 }

 function setStart(uint _start) public onlyOwner{
   start = _start;
 }

 function setDays(uint _days) public onlyOwner{
   dayMax = _days;
 }

 function setAddrERC20(address _tokenAddr) public onlyOwner{
   require(_tokenAddr != address(0));
   token = IERC20(_tokenAddr);
 }
}

我在 test.js 中的函式

it(`Buy with account Investor1 4 ether = 12000 tokens`, async () => {
           await contractInstance.initialize();
           await contractInstance.buyTokens({
               from: investor1,
               value: web3.utils.toWei("4", "ether"),
               gas: 200000
           })
           let total = await coinInstance.balanceOf(investor1);
           expect(web3.utils.fromWei(total)).to.be.equal("12000");
       });

輸出:

Validate pre-sales from account privateSales
        Buy with account Investor1 4 ether = 12000 tokens:
    Error: Returned error: VM Exception while processing transaction: revert You have reached the purchase limit -- Reason given: You have reached the purchase limit.  ```

您將 wei ( msg.value) 與看起來不像 wei 的東西(而是 ethers/bnb)進行比較,uint256 buyMax = 5;

要比較並獲得您在評論中描述的行為,您需要乘以buyMax10^18(或使用“ether”單位uint256 buyMax = 5 ether;,這是 10^18 的快捷方式)

為清楚起見進行編輯:如果您將變數替換為它們的值,則您的測試失敗:if(amountMax >= buyMax)因為您正在測試if(5000000000000000000 >= 5)

引用自:https://ethereum.stackexchange.com/questions/114047