Comprobando si se permite el retiro del contrato

Estoy tratando de conceptualizar cómo se escribiría un tipo específico de contrato inteligente.

El contrato básicamente manejaría depósitos y retiros de ETH o algún tipo de token ERC20.

Los saldos luego se usarían para jugar varios juegos fuera de cadena, en su mayoría cosas de estilo de casino para múltiples jugadores como Texas Holdem. Los juegos están fuera de la cadena porque requieren muchas operaciones y las tarifas de Tx no serían fáciles de usar.

Los usuarios aumentarían (o disminuirían) sus saldos dentro del contrato al jugar estos juegos.

Quiero darles a los usuarios la posibilidad de retirar sus saldos a sus billeteras en cualquier momento, pero tengo que poder verificar los servidores del juego para asegurarme de que no están actualmente en un juego mientras intentan retirar.

Estoy tratando de evitar un escenario en el que un jugador ingrese a un juego (como el póquer) apueste su saldo fuera de la cadena pero lo retire del contrato mientras el juego está en progreso. Entonces, si pierden, no hay saldo para transferir al otro jugador.

No estoy seguro de cuál sería el enfoque correcto para hacer esto. ¿Podría ayudar de alguna manera crear una billetera token/personalizada u oralizar el retiro?

¡Cualquier idea sería muy apreciada!

Gracias

Respuestas (3)

Puede hacer que el retiro se fije en el tiempo durante una hora y requiera un depósito de seguridad. Si puede probar que el usuario todavía estaba jugando a través de firmas de los canales estatales, puede probar que intentó retirarse de manera nefasta y reclamar su retiro y depósito de seguridad.

¿Podría explicar la implementación de "firmas de canales estatales"? No estoy familiarizado con eso.
Debe echar un vistazo a Plasma Cash -> karl.tech/plasma-cash-simple-spec , ya que arrojará algo de luz sobre cómo hacer la gestión de activos fuera de la cadena y la resolución de conflictos en la cadena.

Tienes un juego fuera de la cadena, por lo que hay un elemento de confianza en los servidores del juego. Tiene fondos separados en juego de los fondos que se pueden retirar libremente (no gravados).

Una formulación simple sería transferir fondos al cuidado del sistema de juego y su proceso de contabilidad hasta que los fondos se retiren del juego en vivo y estén disponibles para retirar.

En caso de que no esté claro.

Alice tiene 10 éter. Ella compra 5 fichas por 5 ether y tiene 5 ether disponibles para retirar. Ella cobra sus fichas cuando no están en juego, pero eso es una preocupación del servidor de juegos porque sabe cuáles son "libres y claras" y cuáles están en juego. Cuando Alice vende, digamos 7 fichas (Alice de la suerte), recupera 7 ether.

Un contrato puede manejar el depósito y retiro de éter. Puede gestionar el intercambio de fichas quitando el éter (transferencia al propietario) y emitiendo un evento. Es responsabilidad del servidor del juego acreditarle fichas de casino. El contrato simplemente emitirá un evento para que sepa lo que debe hacer.

De manera similar, cuando Alice cobra sus fichas, el servidor del juego se llevará las fichas y transferirá la cantidad correspondiente de éter a la cuenta de Alice. Alice puede retirar éter para salir del establecimiento.

Este es un ejemplo demasiado simplificado para darle algunas ideas.

pragma solidity 0.5.1;

contract Holdem {

    mapping(address => uint) public balances;

    event LogDeposit(address sender, uint amount);
    event LogWithdrawal(address receiver, uint amount);
    event LogTransfer(address sender, address receiver, uint amount);

    function depost() public payable {
        balances[msg.sender] += msg.value;
        emit LogDeposit(msg.sender, msg.value);
    }

    function withdraw(uint amount) public {
        uint bal = balances[msg.sender];
        require(bal >= amount, "Insufficient Funds.");
        balances[msg.sender] -= amount;
        emit LogWithdrawal(msg.sender, amount);
        msg.sender.transfer(amount);
    }

    function transfer(uint amount, address receiver) public {
        uint bal = balances[msg.sender];
        require(bal >= amount, "Insufficient Funds.");
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        emit LogTransfer(msg.sender, receiver, amount);
    }

}

La transfer()función permite que Alicia dé a la casa y que la casa dé a Alicia. Emite un evento que es suficiente para que una casa honesta dé cuenta de los fondos recibidos.

Los observadores astutos notarán que no hay nada que impida que la casa retire las ganancias (en el caso honesto) o todo (en el caso de la estafa de salida). Sería necesario agregar restricciones estrictas sobre la capacidad de la casa para retirar fondos (las fichas deben estar garantizadas), así como evidencia de que los juegos son justos antes de que las partes "fuera de la cadena" de dicho sistema sean confiables.

Espero eso ayude.

De lo que estás hablando es esencialmente del concepto de "orcales" fuera de la cadena. Para ver ejemplos de cómo se hace esto, puede consultar instalaciones como las proporcionadas por https://chain.link .

La metodología general consiste en crear funciones de contrato a las que se puede llamar mediante un código que se ejecuta fuera de la cadena de bloques (de la misma manera que una billetera o dapp llama a un contrato en la cadena), con el fin de proporcionar datos del mundo fuera de la cadena.

En un escenario como el que está describiendo, sus servidores de juegos fuera de la cadena necesitarían "bloquear" una cierta cantidad de valor en la cadena y luego "desbloquear" cualquier valor que no se haya gastado durante el juego. Obviamente, las funciones de contrato a las que llaman tendrían que ser funciones de "solo propietario" (es decir, tener controles de acceso) y es posible que también desee participar en alguna criptografía de los datos intercambiados. Todo en la cadena es visible, incluso si las variables se declaran "privadas" en Solidity. Por lo tanto, mantener la privacidad de la información que se transmite dentro o fuera de la cadena no es trivial.