我正在创建一个简单的 ICO 合约,一旦合约收到以太币,它就会将购买的代币数量发送给买家,然后将收到的以太币发送到另一个钱包,我整天都在重新混合上测试它,但是,合约收到以太币,但不将以太币发送到钱包,买家也没有收到她的以太币。这是购买功能。
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import "./SafeMath.sol";
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(
address owner,
address spender
) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
function burn(uint256 _value) external returns (bool success);
}
contract Crowdsale {
using SafeMath for uint256;
// The token being sold
IERC20 public token;
// Address where funds are collected
IERC20 public wallet;
// How many token units a buyer gets per wei
uint256 public rate;
// Amount of wei raised
uint256 public weiRaised;
/**
* Event for token purchase logging
* @param purchaser who paid for the tokens
* @param beneficiary who got the tokens
* @param value weis paid for purchase
* @param amount amount of tokens purchased
*/
event TokenPurchase(
address indexed purchaser,
address indexed beneficiary,
uint256 value,
uint256 amount
);
/**
* @param _rate Number of token units a buyer gets per wei
* @param _wallet Address where collected funds will be forwarded to
* @param _token Address of the token being sold
*/
constructor(uint256 _rate, address _wallet, address _token) {
require(_rate > 0);
require(_wallet != address(0));
require(_token != address(0));
rate = _rate;
wallet = IERC20(_wallet);
token = IERC20(_token);
}
/**
* @dev fallback function ***DO NOT OVERRIDE***
// */
fallback() external payable {
buyTokens(msg.sender);
}
// receive() external payable{}
/**
* @dev low level token purchase ***DO NOT OVERRIDE***
* @param _beneficiary Address performing the token purchase
*/
function buyTokens(address _beneficiary) public payable {
uint256 weiAmount = msg.value;
_preValidatePurchase(_beneficiary, weiAmount);
// calculate token amount to be created
uint256 tokens = _getTokenAmount(weiAmount);
// update state
weiRaised = weiRaised.add(weiAmount);
_processPurchase(_beneficiary, tokens);
emit TokenPurchase(msg.sender, _beneficiary, weiAmount, tokens);
_updatePurchasingState(_beneficiary, weiAmount);
_forwardFunds();
_postValidatePurchase(_beneficiary, weiAmount);
}
/**
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations.
* @param _beneficiary Address performing the token purchase
* @param _weiAmount Value in wei involved in the purchase
*/
function _preValidatePurchase(
address _beneficiary,
uint256 _weiAmount
) internal pure {
require(_beneficiary != address(0));
require(_weiAmount != 0);
}
/**
* @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met.
* @param _beneficiary Address performing the token purchase
* @param _weiAmount Value in wei involved in the purchase
*/
function _postValidatePurchase(
address _beneficiary,
uint256 _weiAmount
) internal {
// optional override
}
// 0x4815A8Ba613a3eB21A920739dE4cA7C439c7e1b1
// 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db
/**
* @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
* @param _beneficiary Address performing the token purchase
* @param _tokenAmount Number of tokens to be emitted
*/
function _deliverTokens(
address _beneficiary,
uint256 _tokenAmount
) internal {
token.transfer(_beneficiary, _tokenAmount);
}
/**
* @dev Executed when a purchase has been validated and is ready to be executed. Not necessarily emits/sends tokens.
* @param _beneficiary Address receiving the tokens
* @param _tokenAmount Number of tokens to be purchased
*/
function _processPurchase(
address _beneficiary,
uint256 _tokenAmount
) internal {
_deliverTokens(_beneficiary, _tokenAmount);
}
/**
* @dev Override for extensions that require an internal state to check for validity (current user contributions, etc.)
* @param _beneficiary Address receiving the tokens
* @param _weiAmount Value in wei involved in the purchase
*/
function _updatePurchasingState(
address _beneficiary,
uint256 _weiAmount
) internal {
// optional override
}
/**
* @dev Override to extend the way in which ether is converted to tokens.
* @param _weiAmount Value in wei to be converted into tokens
* @return Number of tokens that can be purchased with the specified _weiAmount
*/
function _getTokenAmount(
uint256 _weiAmount
) internal view returns (uint256) {
return _weiAmount.mul(rate);
}
/**
* @dev Determines how ETH is stored/forwarded on purchases.
*/
function _forwardFunds() internal {
// bool sent = wallet.transfer(address(wallet),msg.value);
wallet.transfer(address(wallet), msg.value);
// require(sent, "Transaction failed");
}
function getWallet() public view returns (uint) {
return address(wallet).balance;
}
function getTokenBalance() public view returns (uint) {
return address(token).balance;
}
}
我们需要首先就您的目标达成一致:
任何人都可以按照您预先定义的价格使用链上的原生代币购买您的代币。一旦有人成功购买了代币,则 msg.value 中可访问的原生代币数量将被转发到您也预定义的钱包。
此外,关于您的合约的构建方式,您似乎计划将 ERC20 代币与 Crowdsale 合约分开部署。如果没有在下面评论,您希望 Crowdsale 也部署 ERC20 代币。
达成目标后,需要进行多项修复才能使用当前代码实现该目标。
首先,ERC20代币的部署顺序和供应情况:
其次,我们需要修复您合约的部分内容,以便能够转发买家用来购买您的代币的原生代币:
// Address where funds are collected
address public wallet;
_forwardFunds(msg.value);
/**
* @dev Determines how ETH is stored/forwarded on purchases.
*/
function _forwardFunds(uint256 _value) internal {
// bool sent = wallet.transfer(address(wallet),msg.value);
address payable receiver = payable(wallet);
receiver.transfer(_value);
// require(sent, "Transaction failed");
}
//Required to be able to accept native currency of the network(ETH)
event Received(address, uint256);
receive() external payable {
emit Received(msg.sender, msg.value);
}
完整代码:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import "./SafeMath.sol";
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(
address owner,
address spender
) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
function burn(uint256 _value) external returns (bool success);
}
contract Crowdsale {
using SafeMath for uint256;
// The token being sold
IERC20 public token;
// Address where funds are collected
address public wallet;
// How many token units a buyer gets per wei
uint256 public rate;
// Amount of wei raised
uint256 public weiRaised;
/**
* Event for token purchase logging
* @param purchaser who paid for the tokens
* @param beneficiary who got the tokens
* @param value weis paid for purchase
* @param amount amount of tokens purchased
*/
event TokenPurchase(
address indexed purchaser,
address indexed beneficiary,
uint256 value,
uint256 amount
);
/**
* @param _rate Number of token units a buyer gets per wei
* @param _wallet Address where collected funds will be forwarded to
* @param _token Address of the token being sold
*/
constructor(uint256 _rate, address _wallet, address _token) {
require(_rate > 0);
require(_wallet != address(0));
require(_token != address(0));
rate = _rate;
wallet = _wallet;
token = IERC20(_token);
}
/**
* @dev fallback function ***DO NOT OVERRIDE***
// */
fallback() external payable {
buyTokens(msg.sender);
}
// receive() external payable{}
/**
* @dev low level token purchase ***DO NOT OVERRIDE***
* @param _beneficiary Address performing the token purchase
*/
function buyTokens(address _beneficiary) public payable {
uint256 weiAmount = msg.value;
_preValidatePurchase(_beneficiary, weiAmount);
// calculate token amount to be created
uint256 tokens = _getTokenAmount(weiAmount);
// update state
weiRaised = weiRaised.add(weiAmount);
_processPurchase(_beneficiary, tokens);
emit TokenPurchase(msg.sender, _beneficiary, weiAmount, tokens);
_updatePurchasingState(_beneficiary, weiAmount);
_forwardFunds(msg.value);
_postValidatePurchase(_beneficiary, weiAmount);
}
/**
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations.
* @param _beneficiary Address performing the token purchase
* @param _weiAmount Value in wei involved in the purchase
*/
function _preValidatePurchase(
address _beneficiary,
uint256 _weiAmount
) internal pure {
require(_beneficiary != address(0));
require(_weiAmount != 0);
}
/**
* @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met.
* @param _beneficiary Address performing the token purchase
* @param _weiAmount Value in wei involved in the purchase
*/
function _postValidatePurchase(
address _beneficiary,
uint256 _weiAmount
) internal {
// optional override
}
// 0x4815A8Ba613a3eB21A920739dE4cA7C439c7e1b1
// 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db
/**
* @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
* @param _beneficiary Address performing the token purchase
* @param _tokenAmount Number of tokens to be emitted
*/
function _deliverTokens(
address _beneficiary,
uint256 _tokenAmount
) internal {
token.transfer(_beneficiary, _tokenAmount);
}
/**
* @dev Executed when a purchase has been validated and is ready to be executed. Not necessarily emits/sends tokens.
* @param _beneficiary Address receiving the tokens
* @param _tokenAmount Number of tokens to be purchased
*/
function _processPurchase(
address _beneficiary,
uint256 _tokenAmount
) internal {
_deliverTokens(_beneficiary, _tokenAmount);
}
/**
* @dev Override for extensions that require an internal state to check for validity (current user contributions, etc.)
* @param _beneficiary Address receiving the tokens
* @param _weiAmount Value in wei involved in the purchase
*/
function _updatePurchasingState(
address _beneficiary,
uint256 _weiAmount
) internal {
// optional override
}
/**
* @dev Override to extend the way in which ether is converted to tokens.
* @param _weiAmount Value in wei to be converted into tokens
* @return Number of tokens that can be purchased with the specified _weiAmount
*/
function _getTokenAmount(
uint256 _weiAmount
) internal view returns (uint256) {
return _weiAmount.mul(rate);
}
/**
* @dev Determines how ETH is stored/forwarded on purchases.
*/
function _forwardFunds(uint256 _value) internal {
// bool sent = wallet.transfer(address(wallet),msg.value);
address payable receiver = payable(wallet);
receiver.transfer(_value);
// require(sent, "Transaction failed");
}
function getWalletBalance() public view returns (uint) {
return address(wallet).balance;
}
function getTokenBalance() public view returns (uint) {
return address(token).balance;
}
//Required to be able to accept native currency of the network
event Received(address, uint256);
receive() external payable {
emit Received(msg.sender, msg.value);
}
}
附言: 看到你的 getWallet 公共函数的目的是获取钱包余额,所以我将其重命名为 getWalletBalance。