Solidity 智能合約中的退款功能不起作用
我正在嘗試實現一個 HelloWorld 智能合約,將 1:1 乙太幣更改為令牌(儲存在餘額中),反之亦然 - 我可以呼叫支付功能,一切正常,但退款功能不起作用。儘管從合約中扣除了乙太幣和代幣(儲存在餘額中),但當呼叫退款時,乙太幣不會被發送回呼叫者 - 所以它們會消失。我正在研究 Reopten 測試網:
所以你可以看到合約目前有 0.0088 乙太幣,因為我已經用 0.0011 呼叫了兩次退款,但是你可以看到合約沒有發送乙太幣 - 所以它們消失了
https://ropsten.etherscan.io/address/0xaa394f1d64d6193b3189826a7b58e40a56703227
您還可以看到,從一個沒有乙太幣轉移到的地址收到了兩次退款電話……
https://ropsten.etherscan.io/address/0x90a700898b596115c03bb9b99b639ad811d792ff
我究竟做錯了什麼?
pragma solidity ^0.4.23; contract EtherSwap { mapping(address => uint) balances; /* Define variable owner of the type address */ address owner; /* This function is executed at initialization and sets the owner of the contract */ constructor() public { owner = msg.sender; } function() public payable { balances[msg.sender] += msg.value; } function query() public constant returns (uint balance) { return balances[msg.sender]; } function query(address id) public constant returns (uint balance) { return balances[id]; } function refund(uint amountRequested) public { require(amountRequested > 0 && amountRequested <= balances[msg.sender]); balances[msg.sender] -= amountRequested; msg.sender.transfer(amountRequested); } /* Function to recover the funds on the contract */ function kill() public { if (msg.sender == owner) selfdestruct(owner); }
}
RAW退款交易:
{“隨機數”:“0x19”,“gasPrice”:“0x098bca5a00”,“gasLimit”:“0x923a”,“為”:“0xAA394f1d64D6193B3189826A7B58e40a56703227”,“值”:“0×00”,“數據”:“0x278ecde10000000000000000000000000000000000000000000000000003e871b540c000”,“鏈ID“:3}
簽署的退款交易:
{“from”:“0x90a700898b596115c03bb9b99b639ad811d792ff”,“nonce”:“0x19”,“gasPrice”:“0x098bca5a00”,“gasLimit”:“0x923a”,“to”:“0xAA394f1d64D6193B31898206A7B5840”,““valuea:“6703A7B5840數據”:“0x278ecde10000000000000000000000000000000000000000000000000003e871b540c000”,“chainId”:3}
ABI:
$$ {“constant”:false,“inputs”:[{“name”:“amountRequested”,“type”:“uint256”}],“name”:“refund”,“outputs”:[],“payable”:false,“stateMutability”:“nonpayable”,“type”:“function”},{“constant”:true,“inputs”:[],“name”:“query”,“outputs”:[{“name”:“balance”,“type”:“uint256”}],“payable”:false,“stateMutability”:“view”,“type”:“function”},{“constant”:false,“inputs”:[],“name”:“kill”,“outputs”:[],“payable”:false,“stateMutability”:“nonpayable”,“type”:“function”},{“constant”:true,“inputs”:[{“name”:“id”,“type”:“address”}],“name”:“query”,“outputs”:[{“name”:“balance”,“type”:“uint256”}],“payable”:false,“stateMutability”:“view”,“type”:“function”},{“inputs”:[],“payable”:false,“stateMutability”:“nonpayable”,“type”:“constructor”},{“payable”:true,“stateMutability”:“payable”,“type”:“fallback”} $$
剛剛發現您可以在 etherscan 上將交易視為“內部交易”——這意味著一切正常
更多關於“內部交易”的資訊可以在這裡找到
順便說一句,您可以簡化它並添加一些標準一致性,以便在調試情況下使用。
刪除這個
function query() public constant returns (uint balance) { return balances[msg.sender]; } function query(address id) public constant returns (uint balance) { return balances[id]; }
並添加
public
到mapping(address => uint) public balances;
您將獲得一個名為balances(address)
. 你不會得到花哨的超載,但你並不真的需要它讓客戶詢問自己。您可以添加事件日誌
event LogDeposit(address sender, uint amount); event LogRefund(address receiver, uint amount);
(映射後將是“正常”)。
然後你可以稍微更新你的備份(只有足夠的氣體)。
function() public payable { balances[msg.sender] += msg.value; LogDeposit(msg.sender, msg.value); }
還有另一個狀態改變函式:
function refund(uint amountRequested) public returns(bool success) { require(amountRequested > 0); require(amountRequested <= balances[msg.sender]); balances[msg.sender] -= amountRequested; LogRefund(msg.sender, amountRequested); msg.sender.transfer(amountRequested); return true; }
我冒昧地將
require
up 分成兩個塊並返回一個 bool。只是一些想法可以幫助您和其他人解決正在發生的事情。希望能幫助到你。