Blockchain 使用BNB从合同中购买代币时出现的问题

Blockchain 使用BNB从合同中购买代币时出现的问题,blockchain,solidity,smartcontracts,remix,Blockchain,Solidity,Smartcontracts,Remix,我正在创建这个智能合约,它创建并将所有代币添加到我的钱包中。 然后我把钱包里的所有代币都寄到我的合同里 然而,当我从另一个钱包里给BNB寄去合同时,我想让他归还我合同中的一些代币 执行此操作时,传输失败并发送以下错误消息: 警告!合同执行期间遇到错误[汽油用完] 佩剑是一种天然气,与天然气相反 交易详情: 智能合约: pragma-solidity^0.8.0; 接口IERC20{ 函数totalSupply()外部视图返回(uint256); (地址账户)外部视图返回的功能余额(uint256

我正在创建这个智能合约,它创建并将所有代币添加到我的钱包中。 然后我把钱包里的所有代币都寄到我的合同里

然而,当我从另一个钱包里给BNB寄去合同时,我想让他归还我合同中的一些代币

执行此操作时,传输失败并发送以下错误消息:

警告!合同执行期间遇到错误[汽油用完]

佩剑是一种天然气,与天然气相反

交易详情:

智能合约:

pragma-solidity^0.8.0;
接口IERC20{
函数totalSupply()外部视图返回(uint256);
(地址账户)外部视图返回的功能余额(uint256);
功能允许(地址所有者、地址使用者)外部视图返回(uint256);
功能转移(地址接收人,uint256金额)外部返回(bool);
职能部门批准(地址支出人,uint256金额)外部退货(bool);
函数transferFrom(地址发送方、地址接收方、uint256金额)外部返回(bool);
事件传输(地址索引自,地址索引至,uint256值);
事件批准(地址索引所有者、地址索引支出者、uint256值);}
合同ERC20Basic为IERC20{
字符串public常量name=“ByeSeel”;
字符串公共常量symbol=“BYS”;
uint8公共常量小数=18;
事件批准(地址索引令牌所有者、地址索引支出者、uint令牌);
事件传输(地址索引自、地址索引至、uint令牌);
映射(地址=>uint256)余额;
允许映射(地址=>mapping(地址=>uint256));
uint256总电源=100*10**18;
对uint256使用SafeMath;
构造函数()公共{
余额[消息发送方]=总供应量;
}
函数totalSupply()公共覆盖视图返回(uint256){
返回总供给;
}
函数平衡(地址令牌所有者)公共覆盖视图返回(uint256){
返回余额[令牌所有者];
}
函数传输(地址接收器,uint256 numTokens)公共覆盖返回(bool){

require(numTokens根据BscScan上的事务详细信息,您尝试发送0.1个BNB,而不调用任何函数

您的合同既不具备接受传入BNB的功能,也不具备接受传入BNB的功能

因此,您需要做的就是实现
receive()
函数

contract ERC20Basic is IERC20 {
    // rest of your code

    receive() external payable {
        // can call the buy() function
        buy();
    }
}
您可以在中看到,当您向合同发送100 wei(如果是BNB,则为100 jager)时,
receive()
函数执行
buy()
函数并生成
buy
事件日志

以下是在合同中实现的全部代码:

pragma solidity ^0.8.0;

interface IERC20 {

function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);

function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);


event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
    
}


contract ERC20Basic is IERC20 {

string public constant name = "ByeSeel";
string public constant symbol = "BYS";
uint8 public constant decimals = 18;


//event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
//event Transfer(address indexed from, address indexed to, uint tokens);


mapping(address => uint256) balances;

mapping(address => mapping (address => uint256)) allowed;

uint256 totalSupply_ = 100 * 10 ** 18;

using SafeMath for uint256;

constructor() public {
balances[msg.sender] = totalSupply_;
}

function totalSupply() public override view returns (uint256) {
return totalSupply_;
}

function balanceOf(address tokenOwner) public override view returns (uint256) {
    return balances[tokenOwner];
}

function transfer(address receiver, uint256 numTokens) public override returns (bool) {
    require(numTokens <= balances[msg.sender]);
    balances[msg.sender] = balances[msg.sender].sub(numTokens);
    balances[receiver] = balances[receiver].add(numTokens);
    emit Transfer(msg.sender, receiver, numTokens);
    return true;
}

function approve(address delegate, uint256 numTokens) public override returns (bool) {
    allowed[msg.sender][delegate] = numTokens;
    emit Approval(msg.sender, delegate, numTokens);
    return true;
}

function allowance(address owner, address delegate) public override view returns (uint) {
    return allowed[owner][delegate];
}

function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {
    require(numTokens <= balances[owner]);
    require(numTokens <= allowed[owner][msg.sender]);

    balances[owner] = balances[owner].sub(numTokens);
    allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens);
    balances[buyer] = balances[buyer].add(numTokens);
    emit Transfer(owner, buyer, numTokens);
    return true;
}

event Received(address, uint);
 receive() external payable {
 emit Received(msg.sender, msg.value);
}

 }

library SafeMath {
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
  assert(b <= a);
  return a - b;
}

function add(uint256 a, uint256 b) internal pure returns (uint256) {
  uint256 c = a + b;
  assert(c >= a);
  return c;
} }

contract DEX {

    event Bought(uint256 amount);
    event Sold(uint256 amount);
    
    
    IERC20 public token;
    
    constructor() public {
        token = new ERC20Basic();
    }
    
    function buy() payable public {
        uint256 amountTobuy = msg.value;
        uint256 dexBalance = token.balanceOf(address(this));
        require(amountTobuy > 0, "You need to send some Ether");
        require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
        token.transfer(msg.sender, amountTobuy);
        emit Bought(amountTobuy);
    }
    
    function sell(uint256 amount) public {
        require(amount > 0, "You need to sell at least some tokens");
        uint256 allowance = token.allowance(msg.sender, address(this));
        require(allowance >= amount, "Check the token allowance");
        token.transferFrom(msg.sender, address(this), amount);
        payable(msg.sender).transfer(amount);
        emit Sold(amount);
    }
    
    receive() external payable {
        buy();
    }

}
pragma-solidity^0.8.0;
接口IERC20{
函数totalSupply()外部视图返回(uint256);
(地址账户)外部视图返回的功能余额(uint256);
功能允许(地址所有者、地址使用者)外部视图返回(uint256);
功能转移(地址接收人,uint256金额)外部返回(bool);
职能部门批准(地址支出人,uint256金额)外部退货(bool);
函数transferFrom(地址发送方、地址接收方、uint256金额)外部返回(bool);
事件传输(地址索引自,地址索引至,uint256值);
事件批准(地址索引所有者、地址索引支出者、uint256值);
}
合同ERC20Basic为IERC20{
字符串public常量name=“ByeSeel”;
字符串公共常量symbol=“BYS”;
uint8公共常量小数=18;
//事件批准(地址索引令牌所有者、地址索引支出者、uint令牌);
//事件传输(地址索引自、地址索引至、uint令牌);
映射(地址=>uint256)余额;
允许映射(地址=>mapping(地址=>uint256));
uint256总电源=100*10**18;
对uint256使用SafeMath;
构造函数()公共{
余额[消息发送方]=总供应量;
}
函数totalSupply()公共覆盖视图返回(uint256){
返回总供给;
}
函数平衡(地址令牌所有者)公共覆盖视图返回(uint256){
返回余额[令牌所有者];
}
函数传输(地址接收器,uint256 numTokens)公共覆盖返回(bool){

require(numTokens)当您将BNB发送到合同时,我的答案中的代码片段会对您最初提出的错误问题作出反应。它允许您将BNB发送到合同,因此您(或任何用户)可以稍后调用
sell()
函数,合同现在有BNB发送回用户。它不会返回任何代币…如果你想购买代币,你需要直接调用
buy()
函数,或者从
receive()
函数中调用。@EvertonFigueiredo我更新了我的答案,并给出了调用
buy()的示例
receive()
函数中的
函数……您能指定“不工作”是什么意思吗?我能够在Remix中成功地发送ETH(对于BNB应该是相同的),并且没有遇到任何问题:1)在
ERC20Basic
(它们已在
IERC20
中定义)并部署
DEX
。2)部署DEX将
100*10**18
令牌发送到我的部署者地址。3)然后我从同一(部署者)向合同发送了100 wei地址并收到100个令牌。@EvertonFigueiredo我用代码更新了答案。使用Solidity 0.8.1I编译后,我将buy()放在receive()上从ERC20Basic内部。这一定是错误。这是有道理的。用户在发送事务时与
DEX
合同交互-而不是与
ERC20Basic
交互。因此
DEX
合同需要实现
recieve()
功能。很高兴它现在可以工作了。
pragma solidity ^0.8.0;

interface IERC20 {

function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);

function transfer(address recipient, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);


event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
    
}


contract ERC20Basic is IERC20 {

string public constant name = "ByeSeel";
string public constant symbol = "BYS";
uint8 public constant decimals = 18;


//event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
//event Transfer(address indexed from, address indexed to, uint tokens);


mapping(address => uint256) balances;

mapping(address => mapping (address => uint256)) allowed;

uint256 totalSupply_ = 100 * 10 ** 18;

using SafeMath for uint256;

constructor() public {
balances[msg.sender] = totalSupply_;
}

function totalSupply() public override view returns (uint256) {
return totalSupply_;
}

function balanceOf(address tokenOwner) public override view returns (uint256) {
    return balances[tokenOwner];
}

function transfer(address receiver, uint256 numTokens) public override returns (bool) {
    require(numTokens <= balances[msg.sender]);
    balances[msg.sender] = balances[msg.sender].sub(numTokens);
    balances[receiver] = balances[receiver].add(numTokens);
    emit Transfer(msg.sender, receiver, numTokens);
    return true;
}

function approve(address delegate, uint256 numTokens) public override returns (bool) {
    allowed[msg.sender][delegate] = numTokens;
    emit Approval(msg.sender, delegate, numTokens);
    return true;
}

function allowance(address owner, address delegate) public override view returns (uint) {
    return allowed[owner][delegate];
}

function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {
    require(numTokens <= balances[owner]);
    require(numTokens <= allowed[owner][msg.sender]);

    balances[owner] = balances[owner].sub(numTokens);
    allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens);
    balances[buyer] = balances[buyer].add(numTokens);
    emit Transfer(owner, buyer, numTokens);
    return true;
}

event Received(address, uint);
 receive() external payable {
 emit Received(msg.sender, msg.value);
}

 }

library SafeMath {
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
  assert(b <= a);
  return a - b;
}

function add(uint256 a, uint256 b) internal pure returns (uint256) {
  uint256 c = a + b;
  assert(c >= a);
  return c;
} }

contract DEX {

    event Bought(uint256 amount);
    event Sold(uint256 amount);
    
    
    IERC20 public token;
    
    constructor() public {
        token = new ERC20Basic();
    }
    
    function buy() payable public {
        uint256 amountTobuy = msg.value;
        uint256 dexBalance = token.balanceOf(address(this));
        require(amountTobuy > 0, "You need to send some Ether");
        require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
        token.transfer(msg.sender, amountTobuy);
        emit Bought(amountTobuy);
    }
    
    function sell(uint256 amount) public {
        require(amount > 0, "You need to sell at least some tokens");
        uint256 allowance = token.allowance(msg.sender, address(this));
        require(allowance >= amount, "Check the token allowance");
        token.transferFrom(msg.sender, address(this), amount);
        payable(msg.sender).transfer(amount);
        emit Sold(amount);
    }
    
    receive() external payable {
        buy();
    }

}