[P] Cuando se llama a la siguiente transacción: Bank.pay({"from": eth.accounts[0], "value": 1});
, ¿quién recupera el dinero, el propietario del contrato? (Lo siento, me pierdo quién realmente gana el dinero). Y más adelante, ¿cómo podría ese dinero transferirse de nuevo al remitente en otra llamada de función (esto podría verse como un proceso de reembolso)?
Me gustaría llevar a cabo el siguiente escenario, si es posible.
Bank.pay({"from": eth.accounts[0], "value": 1})
.payMeBack()
que se llame. Básicamente, el propietario del dinero no puede gastar msg.value => 1 wei.Bank.payMeBack()
La función del contrato devolverá el dinero (imagínese que es un proceso de reembolso) al Cliente A, si se cumple la condición. Si la condición falla, ahora se debe eliminar el bloqueo del dinero y el dinero se gana mediante el contrato y el propietario del dinero podría gastarlo.Ejemplo de contrato:
pragma solidity ^0.4.8;
contract Bank{
address client;
uint gainedWei;
function pay() payable {
client = msg.sender;
gainedWei = msg.value;
}
function payMeBack() {
if(<some condition check>)
//Some how it has to send back ether to client-A. We know the address we would like to send and the amount.
}
}
Gracias por su valioso tiempo y ayuda.
La respuesta corta es que los contratos son participantes completos, por lo que cuando alguien envía fondos, el contrato tiene los fondos.
El contrato puede entonces decidir si/cuándo enviar los fondos ya quién. En su caso de uso, implica hacer un seguimiento de a quién se le deben fondos. Lo haría a medida que se reciban los fondos.
Ejemplo muy esquemático para ayudar a ilustrar el flujo.
pragma solidity ^0.4.8;
contract Bank{
address public owner;
uint public receivedWei;
uint public returnedWei;
// simple storage pattern descibed here: https://ethereum.stackexchange.com/questions/13167/are-there-well-solved-and-simple-storage-patterns-for-solidity
struct Client {
uint received;
uint returned;
uint clientListPointer;
}
mapping(address => Client) public clientStructs;
address[] public clientList;
event LogReceivedFunds(address sender, uint amount);
event LogReturnedFunds(address recipient, uint amount);
function Bank() {
owner = msg.sender;
}
function getClientCount()
public
constant
returns(uint clientCount)
{
return clientList.length;
}
function isClient(address client)
public
constant
returns(bool isIndeed)
{
if(clientList.length==0) return false;
return clientList[clientStructs[client].clientListPointer]==client;
}
function pay() payable
public
returns(bool success)
{
// push new client, update existing
if(!isClient(msg.sender)) {
clientStructs[msg.sender].clientListPointer = clientList.push(msg.sender)-1;
}
// track cumulative receipts per client
clientStructs[msg.sender].received += msg.value;
receivedWei += msg.value;
LogReceivedFunds(msg.sender, msg.value);
return true;
}
function payMeBack(uint amountToWithdraw)
public
returns(bool success)
{
// if not a client, then throw;
if(!isClient(msg.sender)) throw;
// owed = moneyReceived - moneyAlreadyReturned;
uint netOwed = clientStructs[msg.sender].received - clientStructs[msg.sender].returned;
// cannot ask for more than is owed
if(amountToWithdraw > netOwed) throw;
// safe-send pattern
// keep track of money returned
// to this client (user)
clientStructs[msg.sender].returned += amountToWithdraw;
// and overall (contract)
returnedWei += amountToWithdraw;
LogReturnedFunds(msg.sender, amountToWithdraw);
if(!msg.sender.send(amountToWithdraw)) throw;
return true;
}
}
Aquí está en Remix. 10 depositados, luego 9 retirados. Totales acumulados y saldos de clientes.
Espero eso ayude.
La dirección en la que se implementa el contrato recibe el pago. Depende del contrato administrar cualquier saldo que tenga.
Para enviar ese valor a otro objeto de dirección, llame al address
miembro transfer(value)
. Así que para llenar tu payMeBack()
...
function payMeBack() {
require(<some condition>);
if(!client.transfer(gainedWei)) throw; // transfer in solidity 0.4.10
gainedWei = 0;
}
Hay varios otros address
miembros que podrían usarse como <address>.send(<wei>)
(tiene solo 2300 de gas) o los más técnicos <address>.call.value(<wei>)
y sus extensiones.
(Teniendo en cuenta también que su contrato bancario de ejemplo quemará dinero en el sentido de que se reinicia client
y gainedWei
con cada pago)
Error: Member "transfer" not found or not visible after argument-dependent lookup in address
client.transfer(1);@o0ragman0o.client.send(gainedWei)
. Lo siento, no entendí tu última línea. ¿Cómo contrato bancario se quemará el dinero? @o0ragman0opay()
y por lo tanto solo se conservará la dirección del último pagador y únicamente la cantidad que pague. Bank
Se ignorará
cualquier saldo anterior retenido en la dirección, excepto el último valor de wei que se envió.client.transfer(gainedWei)
el dinero del contrato se transferirá al cliente, ¿verdad? @o0ragman0o.gainedWei += msg.value;
alper
clientStructs[msg.sender].returned
=> lo siento, no obtuve lo que devuelve y cuál es el objetivo de esta variable. @RobHitchensRob Hitchens
payMeBack()
. En el ejemplo, el "cliente" depositó 10 y retiró 9. Se les permitiría retirar 1 más porque recibido - devuelto = adeudado, 10-9=1.uint netOwed = clientStructs[msg.sender].received - clientStructs[msg.sender].returned;
La tapa de la pantalla no muestra el orden de los eventos. LaclientStructs()
función se llamó después de 10 enviados y 9 retirados.alper
Rob Hitchens
alper
clientStructs[msg.sender].received
ya que hacemos el reembolso? como:clientStructs[msg.sender].received - amountToWithdraw
@Rob HitchensRob Hitchens
clientStructs[msg.sender].returned += amountToWithdraw;
unas líneas antes. Dejamos lo recibido solo como un total acumulado de todos los fondos tomados. Tenemos otro total general de devueltos. la diferencianetOwed
es Creo que está rastreando todo. No es la única forma de hacerlo. Es una cuestión de gusto personal. Lo importante a tener en cuenta es evitar el desbordamiento/desbordamiento.