Solidity
使用 Safemath 子並添加
好吧,我正在創建一份合約作為我的 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;
要比較並獲得您在評論中描述的行為,您需要乘以
buyMax
10^18(或使用“ether”單位uint256 buyMax = 5 ether;
,這是 10^18 的快捷方式)為清楚起見進行編輯:如果您將變數替換為它們的值,則您的測試失敗:
if(amountMax >= buyMax)
因為您正在測試if(5000000000000000000 >= 5)