Solidity

嘗試在 erc20 中添加應付功能時出錯

  • October 23, 2021

網上大部分的 ERC20 例子都有這個功能:

// ------------------------------------------------------------------------
// Don't accept ETH
// ------------------------------------------------------------------------
function () public payable {
   revert();
}

但是,我想在 Ropsten 上部署一個 ERC20 代幣,使用者可以在其中發送 ETH 並接收我的代幣作為回報所以我嘗試刪除這個函式並將其替換為:

uint public sellPrice =0.5;


function setPrices(uint newSellPrice) public onlyOwner {
   sellPrice = newSellPrice;
}


function buy(uint256 payload) public payable {
   uint amount = safeDiv(msg.value, sellPrice);               
  //balances[msg.sender] += amount; //I commented this out cuz im not sure if I need it

   transferFrom(owner, msg.sender, amount);


}

可悲的是,這不起作用..我收到此錯誤:警告!合約執行過程中遇到的錯誤

$$ Reverted $$ 注意:我使用元遮罩發送 Ropsten Ether .. 我沒有放任何十六進制數據(因為我想,因為這是唯一的 paypal 功能,也許我不需要它?)另外,我不知道這個的十六進制數據函式..所以也許是另一個問題,如何獲取未命名函式的十六進制數據?

更新

我已經嘗試了以下建議的解決方案,這是更新後的契約

epragma solidity ^0.4.20;



contract SafeMath {
function safeAdd(uint a, uint b) public pure returns (uint c) {
   c = a + b;
   require(c >= a);
}
function safeSub(uint a, uint b) public pure returns (uint c) {
   require(b <= a);
   c = a - b;
}
function safeMul(uint a, uint b) public pure returns (uint c) {
   c = a * b;
   require(a == 0 || c / a == b);
}
function safeDiv(uint a, uint b) public pure returns (uint c) {
   require(b > 0);
   c = a / b;
}

}

 contract ERC20Interface {
function totalSupply() public view returns (uint);
function balanceOf(address tokenOwner) public view returns (uint balance);
function allowance(address tokenOwner, address spender) public view returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);

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

}

contract ApproveAndCallFallBack {
function receiveApproval(address from, uint256 tokens, address token, bytes data) public;

}

contract Owned {
address public owner;
address public newOwner;

event OwnershipTransferred(address indexed _from, address indexed _to);

function Owned() public {
   owner = msg.sender;
}

modifier onlyOwner {
   require(msg.sender == owner);
   _;
}

function transferOwnership(address _newOwner) public onlyOwner {
   newOwner = _newOwner;
}
function acceptOwnership() public {
   require(msg.sender == newOwner);
   OwnershipTransferred(owner, newOwner);
   owner = newOwner;
   newOwner = address(0);
}

}

contract FToken is ERC20Interface, Owned, SafeMath {
string public symbol;
string public  name;
uint8 public decimals;
uint public _totalSupply;


mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;


function FToken() public {
   symbol = "fff";
   name = "FAdi Token";
   decimals = 18;
   _totalSupply = 1000000000;

   balances[owner] = _totalSupply;
   Transfer(address(0), owner, _totalSupply);
}


function totalSupply() public view returns (uint) {
   return _totalSupply - balances[address(0)];
}



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



function transfer(address to, uint tokens) public returns (bool success) {
   balances[msg.sender] = safeSub(balances[msg.sender], tokens);
   balances[to] = safeAdd(balances[to], tokens);
   Transfer(msg.sender, to, tokens);
   return true;
}



function approve(address spender, uint tokens) public returns (bool success) {
   allowed[msg.sender][spender] = tokens;
   Approval(msg.sender, spender, tokens);
   return true;
}


function transferFrom(address from, address to, uint tokens) public returns (bool success) {
   balances[from] = safeSub(balances[from], tokens);
   allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
   balances[to] = safeAdd(balances[to], tokens);
   Transfer(from, to, tokens);
   return true;
}

function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
   return allowed[tokenOwner][spender];
}



function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
   allowed[msg.sender][spender] = tokens;
   Approval(msg.sender, spender, tokens);
   ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
   return true;
}


uint public sellPrice =5;


function setPrices(uint newSellPrice) public onlyOwner {
   sellPrice = newSellPrice;
}


function buy() public payable returns (bool success) {

   uint amount = safeMul(msg.value, sellPrice);              // calculates the amount

   //balances[msg.sender] += amount;
   if (approve(owner, amount))

   transferFrom( owner,msg.sender, amount);


}


function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
   return ERC20Interface(tokenAddress).transfer(owner, tokens);
}

}

可悲的是它沒有用..同樣的錯誤(契約執行期間遇到的錯誤

$$ Reverted $$)

兩件事情。

首先,這是一種錯誤的方法。您應該將代幣的定義和記賬與代幣的報價/銷售分開。這將為您留下一個解決良好的令牌,例如 openzeppelin,沒有任何更改,因此您可以確信很多可能會按預期工作。您還將擁有一份銷售契約。

創建 ERC20 後,所有者/鑄幣者/部署者通常擁有 100% 的供應。他們使用正常.transfer方法將部分或全部代幣發送到銷售合約。銷售合約的工作是用手頭的代幣交換收到的 ETH。

如果有幫助,可以考慮一個檸檬水攤。檸檬水攤的工作是將美味的檸檬水(它必須首先擁有)換成一定數量的美元。美元和檸檬水(ETH 和代幣)沒有與銷售過程相關的內置屬性。試圖這樣做只會摻雜他們設計的純潔性。

第二件事。這條線會讓你陷入困境。

uint public sellPrice =0.5;

由於賣價是一個無符號整數,0.5= 0. 這導致函式中的“除以零” buy()。考慮乘以 2 ( .mul(uint(2)) 而不是除以0.5

希望能幫助到你。

更新

Shane 對您使用transferFrom. 你沒有正確使用它。但是,由於銷售過程/契約可能已經持有要出售的代幣庫存,transfer(receiver, amount)因此正常就足夠了。

解決方案正如 Rob Hitchens 所提到的……使用簡單的轉移方法。但是,請確保您使用事件傳輸,而不是他編寫的傳輸函式(帶有小 t)。

Transfer 事件需要 3 個參數,而傳輸函式需要 2 個參數

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