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