A pagar: Enviado - Importe retenido - Mecanismo Sent_back (Reembolso)

[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.

  1. El Cliente A envía algo de dinero (digamos 1 wei) a la función del contrato, a través de las siguientes llamadas del Cliente_A: Bank.pay({"from": eth.accounts[0], "value": 1}).
  2. Ese dinero debe estar bloqueado para ser utilizado por el ganador hasta payMeBack()que se llame. Básicamente, el propietario del dinero no puede gastar msg.value => 1 wei.
  3. Cuando Client_A llama a lo siguiente: 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.

Respuestas (2)

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.

ingrese la descripción de la imagen aquí

Espero eso ayude.

clientStructs[msg.sender].returned=> lo siento, no obtuve lo que devuelve y cuál es el objetivo de esta variable. @RobHitchens
Total de dinero devuelto a un cliente específico. Se agregaron algunos comentarios a 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. La clientStructs()función se llamó después de 10 enviados y 9 retirados.
¿Quién podría decidir el monto de la devolución, el dueño del contrato? también devuelto podría verse como cantidad de reembolso? @Rob Hitchens.
Los usuarios pueden depositar y retirar sus depósitos (o menos), pero no pueden sobregirar sus cuentas. El usuario envía un parámetro para la cantidad que le gustaría retirar.
Pequeña P: en la función de pago en la última línea, ¿deberíamos actualizar clientStructs[msg.sender].receivedya que hacemos el reembolso? como: clientStructs[msg.sender].received - amountToWithdraw@Rob Hitchens
No. Lo hacemos 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 diferencia netOwedes 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.

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 addressmiembro 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 addressmiembros 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 clienty gainedWeicon cada pago)

Me he enfrentado al siguiente error: Error: Member "transfer" not found or not visible after argument-dependent lookup in addressclient.transfer(1);@o0ragman0o.
siguientes obras: client.send(gainedWei). Lo siento, no entendí tu última línea. ¿Cómo contrato bancario se quemará el dinero? @o0ragman0o
Cualquier persona puede realizar un pago a la pay()y por lo tanto solo se conservará la dirección del último pagador y únicamente la cantidad que pague. BankSe ignorará cualquier saldo anterior retenido en la dirección, excepto el último valor de wei que se envió.
Oh, lo tengo, tienes razón, fue solo un ejemplo simple, podemos arreglarlo con un mapeo adicional. @o0ragman0o
Aquí: client.transfer(gainedWei)el dinero del contrato se transferirá al cliente, ¿verdad? @o0ragman0o.
Sí. También asegúrese de agregar al saldo, no solo asignargainedWei += msg.value;