¿Transferir todos los msg.sender.balance al contrato, sin requerir que el usuario ingrese el msg.value?

¿Hay alguna manera de drenar todo el saldo del usuario al contrato o a la dirección de pago externa, sin requerir que el usuario ingrese el valor del mensaje?

La versión más intuitiva que tenía se parece un poco a esto en solidity 0.5.0:

address(this).transfer(msg.sender.balance)

Sin embargo, parece que la dirección del contrato no es inherentemente pagable, así que primero traté de convertirla en una dirección pagadera:

address payable payableContract = address(uint160(address(this)))

Pero tampoco parece funcionar. Alguien me sugirió que buscara en Contract Factory, lo que podría resolver el problema. ¿Cuál sería la mejor manera de sortearlo para lograr el mismo resultado?

Un contrato no puede tomar por la fuerza el éter de un usuario.
@smarx ¿Hay alguna forma de que el usuario autorice previamente la transacción?
La única forma en que se puede transferir el saldo de una cuenta de propiedad externa es si esa cuenta envía una transacción que transfiere ese éter.
@smarx ¿Te gusta un contrato de depósito en garantía?
¿Estás hablando de balance Eth o balance ERC20? Te mostraré lo que _puedes_hacer, pero centrarte en uno u otro lo simplificará.
@ RobHitchens-B9lab Idealmente para ambos, pero transferir ether es más importante para lo que estoy construyendo actualmente.

Respuestas (1)

Necesitas invertir el flujo de las cosas o esto nunca tendrá sentido.

No hay forma de codificar un contrato para transferir fondos desde la billetera de un usuario. No todos, no algunos, no cualquiera.

address(this).transfer(msg.sender.balance)

Eso significa que el destino ( to) es address(this)y el monto es el msg.sendersaldo de . from: addresses implícitamente address(this) porque nada más es posible . Por lo tanto, fromno se menciona en la sintaxis.

Lo que realmente quiere que suceda es que el usuario firme una transacción que envíe su dinero a su contrato. No sé por qué tiene que ser todo su equilibrio y eso me suena como otro paso en falso de diseño, pero así es como lo harías.

Es una preocupación de front-end. Nuevamente, para enfatizar, porque solo el usuario puede autorizar la transferencia de sus propios fondos. Por el lado del contrato, todo lo que puede hacer es recibirlo, validar la transacción y posiblemente rechazarla si algo está mal.

function depositFunds() public payable {
  // carry on
  // msg.value and msg.sender inform about who and how much
}

En la parte frontal, usaría Web3 o una biblioteca similar para ayudar al usuario a realizar una transacción válida con amount: as much as possible, to: your contract, {gas: amount, gasPrice: bid}.

El usuario tiene que pagar por el gas, y esto reducirá la cantidad de fondos disponibles para enviar a su contrato. Tienes que tener eso en cuenta. Su front-end tendrá que averiguar:

  • estimación de gas para la transacción
  • gasPrice (Coste de éter consumido = estimación de gas * gasPrice)
  • Fondos disponibles para enviar (saldo del usuario - costo consumido), dejando al usuario con exactamente 0 saldo restante.

Si el navegador (o el servidor) realiza el cálculo, se le presentará al usuario la opción de firmar una transacción enviando un monto x y ofertando y por gasolina, con una estimación de gasolina de z, dejándolos con un saldo final de 0.

No me queda claro por qué alguien estaría de acuerdo con tales términos.

Espero eso ayude.

Hola Rob, realmente aprecio tu esfuerzo y tiempo para responder esta pregunta. Disfruto de su caridad y detalles en la respuesta. Queremos crear algo que esencialmente requiera que Alice autorice previamente una transacción pendiente que enviará su saldo completo a Bob en una fecha futura. Por lo tanto, uno de los mayores desafíos de diseño es que no sabemos cuál será ese futuro msg.balance, cuando se cumplan ciertas condiciones.
El enfoque más simple es hacer que Alice coloque algunos fondos en un contrato que solo se liberará a Bob. Bob podría ver que los fondos están bloqueados para él. Mucho depende del caso de uso real que tenga en mente.
¿Hay otros enfoques que puedan solucionarlo creativamente?
Como se le preguntó, nada obvio, pero la forma en que describe "enviar el saldo total" no me parece razonable. Creo que podría estar imponiendo suposiciones ocultas en un caso de uso que debería abordarse de otra manera. Si fueras mi cliente, te preguntaría qué deben saber y hacer Alice y Bob y te seguiría preguntando hasta que lo expliques sin decirme cómo crees que debería codificarse.
Podría decir ELIF, explicarlo como si fuera un usuario final, explicarlo para que mi mamá pueda entenderlo.
ah Una forma de abordar eso es un contrato de billetera (no EOA). Varias partes en el contrato tienen diferentes privilegios. El propietario habitual puede ser un solo firmante que puede hacer las cosas habituales. Un quórum de síndicos posiblemente podría pronunciarse sobre una decisión como la incautación. No es un contrato que intenta hacerle cosas imposibles a la billetera. Es una billetera que se implementa como un contrato. Otra forma de abordarlo es usar la codificación de borrado en la clave privada del propietario para que algo así como 2/3 de los fragmentos puedan volver a ensamblarlo. Gracias por aceptar mi respuesta si te resulta útil.
¿Cómo usamos una billetera que se implementa como un contacto? por cierto me gustan tus sugerencias
Vamos a ser castigados por ser demasiado habladores. Sería una buena pregunta nueva. En esencia, usted hace un contrato que transmite los comandos que el propietario del contrato envía. Podría explorar billeteras multisig para obtener algunas ideas. Tendría potencialmente un "propietario" y un conjunto de delegados que pueden votar para tomar el control a través de transferOwnership(). Por supuesto, hay muchos detalles en los que pensar, por lo que todo se acuerda de antemano. El propietario tendría que cambiar de delegados de vez en cuando.
Gracias por todos los consejos que me has dado hasta ahora. He estado buscando billeteras multi-sig durante la última hora. La comunidad Ethereum definitivamente necesita más personas como tú. ¡Tú eres el hombre, Rob!