無法將 ERC20 代幣從另一個智能合約轉移給發送乙太幣的人
我創建了兩個智能合約,都部署在 Ropsten 測試網路上。我正在使用 MetaMask 進行交易。
- ERC20 代幣的實現如下(請注意,我可以在 MetaMask 中看到我的代幣):
contract AppleToken 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; // ------------------------------------------------------------------------ // Constructor // ------------------------------------------------------------------------ function AppleToken() public { symbol = "AppleToken"; name = "Apple Token"; decimals = 18; _totalSupply = 100000000000000000000000000; balances[0x2cBccb25319231B921fCf02Ec3bc213FcdFAeA15] = _totalSupply; Transfer(address(0), 0x2cBccb25319231B921fCf02Ec3bc213FcdFAeA15, _totalSupply); } // ------------------------------------------------------------------------ // Total supply // ------------------------------------------------------------------------ function totalSupply() public constant returns (uint) { return _totalSupply - balances[address(0)]; } // ------------------------------------------------------------------------ // Get the token balance for account tokenOwner // ------------------------------------------------------------------------ function balanceOf(address tokenOwner) public constant returns (uint balance) { return balances[tokenOwner]; } // ------------------------------------------------------------------------ // Transfer the balance from token owner's account to to account // - Owner's account must have sufficient balance to transfer // - 0 value transfers are allowed // ------------------------------------------------------------------------ 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; } // ------------------------------------------------------------------------ // Token owner can approve for spender to transferFrom(...) tokens // from the token owner's account // // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md // recommends that there are no checks for the approval double-spend attack // as this should be implemented in user interfaces // ------------------------------------------------------------------------ function approve(address spender, uint tokens) public returns (bool success) { allowed[msg.sender][spender] = tokens; Approval(msg.sender, spender, tokens); return true; } // ------------------------------------------------------------------------ // Transfer tokens from the from account to the to account // // The calling account must already have sufficient tokens approve(...)-d // for spending from the from account and // - From account must have sufficient balance to transfer // - Spender must have sufficient allowance to transfer // - 0 value transfers are allowed // ------------------------------------------------------------------------ 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; } // ------------------------------------------------------------------------ // Returns the amount of tokens approved by the owner that can be // transferred to the spender's account // ------------------------------------------------------------------------ function allowance(address tokenOwner, address spender) public constant returns (uint remaining) { return allowed[tokenOwner][spender]; } // ------------------------------------------------------------------------ // Token owner can approve for spender to transferFrom(...) tokens // from the token owner's account. The spender contract function // receiveApproval(...) is then executed // ------------------------------------------------------------------------ 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; } // ------------------------------------------------------------------------ // Don't accept ETH // ------------------------------------------------------------------------ function () public payable { revert(); } // ------------------------------------------------------------------------ // Owner can transfer out any accidentally sent ERC20 tokens // ------------------------------------------------------------------------ function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) { return ERC20Interface(tokenAddress).transfer(owner, tokens); }
} 2. 另一個接收 Ether 的智能合約,它應該與上述給定的智能合約互動,以將我的代幣轉移給 Ether 的發送者。
我正在嘗試實現第 2 點中提到的內容,但是如果我嘗試訪問 ERC20 令牌實例的“轉移”功能,我會收到氣體估計超出錯誤(我嘗試增加氣體限制,沒有工作)。此外,當我嘗試通過 MetaMask 強制交易時,它顯示執行成本為 60001 eth,即使我嘗試僅發送 1 個乙太幣。
這是我的功能的實現
目前,我是 ETH 的發送者,我是 ERC20 代幣的接收者
function sendTokens () public payable returns (uint) { //tokenAddress is the address of the ERC20 token deployed on Ropsten AppleToken appleToken; appleToken = AppleToken(tokenAddress); appleToken.transfer(msg.sender, 10); return appleToken.balanceOf(msg.sender); }
我目前正在發送硬編碼的 10 個令牌用於測試目的。 請注意,我已將 AppleToken 包含在 import “browser/AppleToken.sol” 中;
如果我只執行 appleToken.balanceOf 函式,那麼它什麼也不返回。綜上所述,“transfer”函式存在問題,因為計算的執行成本過高,並且“balanceOf”沒有返回任何內容,甚至沒有返回0。
我是否正確啟動了 AppleToken 的實例?還是我做錯了什麼?
任何幫助,將不勝感激。
謝謝你。
更新
Ropsten上的賬戶公共地址:0x2cBccb25319231B921fCf02Ec3bc213FcdFAeA15
Ropsten 上的 ERC20 令牌地址:0x580156edb25D3c3deD584F1075CcCC5dA4861883
以下是 EquityInvestments 合約的完整程式碼:
我已經刪除了程式碼中不必要的東西,因為我沒有呼叫這些函式或使用為我面臨的問題定義的一些變數
pragma solidity ^0.4.16; import "browser/AppleToken.sol"; contract EquityInvestments { AppleToken appleToken; Group [] _Groups; uint PriceEth = 1; address tokenAddress = 0x580156edb25D3c3deD584F1075CcCC5dA4861883; mapping (address => mapping(uint=>UserInvestment)) private _UserInvestments; function EquityInvestments () public { _Groups.push(Group({ GroupID: 1, GroupName: "Google", TotalInvestment: 0, GroupPriceDollars: 200, GroupPriceEth: 1 })); _Groups.push(Group({ GroupID: 2, GroupName: "Tesla", TotalInvestment: 0, GroupPriceDollars: 200, GroupPriceEth: 1 })); _Groups.push(Group({ GroupID: 3, GroupName: "Apple", TotalInvestment: 0, GroupPriceDollars: 200, GroupPriceEth: 1 })); } struct Group { uint GroupID; string GroupName; uint TotalInvestment; uint GroupPriceDollars; uint GroupPriceEth; } function sendTokens () public payable returns (uint) { appleToken = AppleToken(tokenAddress); // return appleToken.balanceOf(msg.sender); // appleToken.approve(this, 10); require(appleToken.transfer(msg.sender, 10)); return appleToken.balanceOf(msg.sender); } }
我看不出代幣合約有什麼問題。
關於第二個,你應該這樣做:
function sendTokens () public payable returns (uint) { AppleToken appleToken = AppleToken(tokenAddress); require(appleToken.transfer(msg.sender, 10)); return appleToken.balanceOf(msg.sender); }
- 無需聲明 appleToken 變數然後設置它,您可以將兩者結合起來。
- 確保這
tokenAddress
是正確的。require
在進行令牌傳輸時始終使用 a !不要認為它像 for 的transfer
方法那樣工作ether
,它處理失敗並會為你拋出。編輯 :
我已經測試了契約,它工作正常。我認為您只是忘記向
EquityInvestments
合約發送代幣,因此代幣餘額msg.sender
保持在0
.