pragmasolidity^0.4.20;interfaceIERC5528{functionescrowFund(address_to,uint256_value)publicreturns(bool);functionescrowRefund(address_from,uint256_value)publicreturns(bool);functionescrowWithdraw()publicreturns(bool);}contractPayableContractisIERC5528,IERC20{/*
General ERC20 implementations
一般的 ERC20 实现
*/function_transfer(addressfrom,addressto,uint256amount)internal{uint256fromBalance=_balances[from];require(fromBalance>=amount,"ERC20: transfer amount exceeds balance");_balances[from]=fromBalance-amount;_balances[to]+=amount;}functiontransfer(addressto,uint256amount)publicreturns(bool){addressowner=msg.sender;_transfer(owner,to,amount);returntrue;}functionescrowFund(address_to,uint256_value)publicreturns(bool){boolres=IERC5528(to).escrowFund(msg.sender,amount);require(res,"Fund Failed");_transfer(msg.sender,to,amount);returntrue;}functionescrowRefund(address_from,uint256_value)publicreturns(bool){boolres=IERC5528(_from).escrowRefund(msg.sender,_value);require(res,"Refund Failed");_transfer(_from,msg.sender,_value);returntrue;}}contractEscrowContractisIERC5528{enumState{Inited,Running,Success,Closed}structBalanceData{addressaddr;uint256amount;}address_addrSeller;address_addrBuyer;BalanceData_fundSeller;BalanceData_fundBuyer;EscrowStatus_status;constructor(addresssellerContract,addressbuyerContract){_addrSeller=sellerContract;_addrBuyer=buyerContract;_status=State.Inited;}functionescrowFund(address_to,uint256_value)publicreturns(bool){if(msg.sender==_addrSeller){require(_status.state==State.Running,"must be running state");_fundSeller.addr=_to;_fundSeller.amount=_value;_status=State.Success;}elseif(msg.sender==_addrBuyer){require(_status.state==State.Inited,"must be init state");_fundBuyer.addr=_to;_fundBuyer.amount=_value;_status=State.Running;}else{require(false,"Invalid to address");}returntrue;}functionescrowRefund(address_from,uint256amount)publicreturns(bool){require(_status.state==State.Running,"refund is only available on running state");require(msg.sender==_addrBuyer,"invalid caller for refund");require(_fundBuyer.addr==_from,"only buyer can refund");require(_fundBuyer.amount>=amount,"buyer fund is not enough to refund");_fundBuyer.amount=_fundBuyer.amount-amountreturntrue;}functionescrowWithdraw()publicreturns(bool){require(_status.state==State.Success,"withdraw is only available on success state");uint256common=MIN(_fundBuyer.amount,_fundSeller.amount);if(common>0){_fundBuyer.amount=_fundBuyer.amount-common;_fundSeller.amount=_fundSeller.amount-common;// Exchange
IERC5528(_addrSeller).transfer(_fundBuyer.addr,common);IERC5528(_addrBuyer).transfer(_fundSeller.addr,common);// send back the remaining balances
// 发送回剩余的余额
if(_fundBuyer.amount>0){IERC5528(_addrBuyer).transfer(_fundBuyer.addr,_fundBuyer.amount);}if(_fundSeller.amount>0){IERC5528(_addrSeller).transfer(_fundSeller.addr,_fundSeller.amount);}}_status=State.Closed;}}
理由
这些接口涵盖了托管操作的可退款问题。
建议的 3 个函数(escrowFund、escrowRefund 和 escrowWithdraw)基于 EIP-20 中的 transfer 函数。