Cómo se recupera el saldo del token ERC20 durante la reversión de la cadena Ethereum

Mi respuesta:

Ok, el problema es realmente con Ganache... Si uso geth, todo está bien.

... ... perdón por tu tiempo ...

---------------- La pregunta original --------------------

Según tengo entendido, los saldos de tokens ERC20 se almacenan en la prueba de almacenamiento , lo que cambiará con el tiempo. Además, token.balanceOf(accountHash, {}, blockNumber)parece devolver solo el saldo más reciente sin importar cuál blockNumbersea. Me pregunto si la cadena Ethereum retrocede y luego crece a lo largo de una nueva cadena, ¿cómo se tratan los saldos de tokens ERC20?

Quiero aclarar un poco sobre el Rollbackaquí. Considere una cadena simplificada con solo 8 bloques, etiquetados por el orden en que se agregan a la cadena (no el número de bloque que define la altura del bloque).

# blocks are labeled by the order they are added to the chain
               /--[6]<--[7]<--[8]
              /
[1]<--[2]<--[3]<--[4]<--[5]

Digamos que hay transacciones sobre un token (ERC20) en todos estos bloques.

Cuando [5]se agrega a la cadena, está en la cadena más larga y token.balanceOf['0xAA']me da balance1.

Ahora suponga [6][7][8]que se agregan a [3], esta rama se convierte en la más larga y todas las transacciones en [4]y [5]se vuelven inválidas.

Ahora supongamos que quiero estar seguro, así que solo me importa el saldo de un token ERC20 (no ETH) en el bloque (N-4). ¿Cómo puedo obtener este saldo?

Hice mi búsqueda y la única forma es usar la API de etherscan, que no está bien para un uso intensivo. Hay otras personas aquí y allá que hacen preguntas similares y siento totalmente su frustración.

Gracias.


Actualización el 5 de abril.

Quiero dar más detalles sobre mis intentos hasta ahora.

1) Estoy usando Ubuntu 16.04 y geth 1.8.2 estable.

2) Empecé ejecutando Ganache, la aplicación con IU gráfica.

3) Mi token es casi el mismo que el del documento oficial https://ethereum.org/token .

4) Implementé el token usando eth.accounts[0]en geth (ganache genera 10 cuentas y cada una tiene 100 ETH iniciales para mí)

$ geth attach http://localhost:8545

var tokenABI = [...];
var tokenFactory = eth.conract(tokenABI);
var byteCode = "0x" + "606..."

var token = tokenFactory.new(
    100,
    "TestCoin",
    "TSC",
    {
        from: eth.accounts[0],  // owner
        data: byteCode,
        gas: 4700000
    }, function(e, contract) {});

5) Hice las siguientes transacciones:

// 3 ETH transactions
eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(5, "ether") });
eth.sendTransaction({from: eth.accounts[1], to: eth.accounts[2], value: web3.toWei(3, "ether") });
eth.sendTransaction({from: eth.accounts[2], to: eth.accounts[3], value: web3.toWei(1, "ether") });

// 3 token transfers
token.transfer(eth.accounts[1], web3.toWei(5, 'ether'), { from: eth.accounts[0] }, function(err, contract) {})
token.transfer(eth.accounts[2], web3.toWei(3, 'ether'), { from: eth.accounts[1] })
token.transfer(eth.accounts[3], web3.toWei(1, 'ether'), { from: eth.accounts[2] })

Para el token, espero que el saldo final sea

account 0: 95
account 1: 2
account 2: 2
account 3: 1

My eth.blockNumbermuestra 7 bloques, lo cual es correcto (3 transferencias éticas, 1 creación de contrato, 3 transferencias de tokens). Cualquier saldo de la cuenta 3 es definitivamente menor que 1 en los bloques anteriores. Sin embargo, el siguiente comando me devuelve 1 éter (en unidades de Wei):

> token.balanceOf(eth.accounts[3], 0, function(err, res) {console.log(err, res};)
null 1000000000000000000
undefined

No importa cómo cambie ese número, de 0 a 7, siempre obtengo el mismo resultado.

Por cierto, no tengo problemas para recuperar la retención de ETH en bloques anteriores. Esto solo ocurre con el Token. Una cosa que noté es que mis eth.syncingdevoluciones false, ¿tal vez porque estoy usando Ganache?

Si la cadena Ethereum retrocede, se recupera el almacenamiento anterior. Digamos que estamos en el bloque 100 y alguien compra 30 tokens del token A, ahora tiene 40 tokens. Aparentemente, esta cadena es una bifurcación: queremos retroceder al bloque 99, por lo tanto, lo hacemos. Ahora esta persona tiene 10 tokens A, su ETH anterior sigue siendo su cantidad anterior de ETH y su transacción aún está en cola (dependiendo de si la nueva bifurcación ha minado su transacción o no). TL; DR en la reversión recuperamos una versión anterior de la cadena de bloques completa.
Nunca he oído hablar de ninguno rollbacken blockchains. Puede que te estés refiriendo a la división de la cadena, cuando alguien extrae 2 tenedores de una cadena de bloques. La cadena más larga gana, y el nodo simplemente elimina la cadena más corta y cambia a la cadena más larga. Los tokens son variables en el estado, por lo que se eligen las variables en la cadena más larga, eso es todo.
@MathematicalRain Entiendo cómo se recuperan ETH. Aquí estoy hablando de los tokens ERC20, que almacenan saldos en el contrato inteligente como un mapeo.
¿ Dónde encontraste esto token.balanceOf(accountHash, {}, blockNumber)? No tiene sentido para mí que esta función deba existir en la cadena. Además, todo el almacenamiento se revierte cuando se bifurca la cadena; así mapeos también. Las reversiones de la cadena Ethereum nunca deberían ocurrir, esto arruina toda la idea detrás de Ethereum, ya que ahora una organización centralizada puede optar por hacer una "bifurcación dura" de toda la cadena.
@MathematicalRain tal vez no lo esté expresando correctamente. pero todo lo que quiero es encontrar el saldo del token ERC20 de una dirección en un bloque específico . es posible? Para esa balanceOffunción, lo leí aquí ethereum.stackexchange.com/questions/42783/…
@MathematicalRain Actualicé mi pregunta. Espero haberme dejado un poco más claro.

Respuestas (1)

Primero aclaremos esta reversión. En el ejemplo que proporciona, se agregan dos bloques (4 y 5) a la cadena. Sin embargo, también se extrae una cadena separada, lo que genera (6,7,8) y, por lo tanto, se hace cargo de la cadena con 4 y 5. Si la red funciona normalmente, podría suceder que aproximadamente al mismo tiempo dos mineros creen un bloque y envíen ellos en la red. En ese momento, no está claro cuál es el bloque 'real' y, por lo tanto, estamos en una bifurcación de la red.

En el ejemplo proporcionado, se agrega otro bloque 5, pero de repente un minero ha generado 5, 6 y 7 y los publica, que ahora es la cadena más larga. Esto implica que este minero tiene >50% del hashrate de la red. Sin embargo, debido a la "suerte", esto puede suceder a veces y, por lo tanto, si desea que sus transacciones se verifiquen de forma segura, debe esperar algunos bloques antes de confirmar esta transacción "de verdad". (Por ejemplo, si envía ETH a alguien, espere 10 bloques y en ese momento es muy difícil para los "mineros malvados" retomar).

Ahora la segunda pregunta, que básicamente se reduce a "¿cómo puedo obtener el saldo de X en un bloque determinado?". Básicamente, desea ejecutar una función en un determinado bloque. Esto se puede hacer a través de web3. Primero genera un objeto de contrato y luego puede usar (javascript)

ERC20Contract.balanceOf(address, BlockNumber, function(){})

(El ejemplo anterior se usa ERC20Contractcomo dirección de contrato, balanceOfes la función de contrato que devuelve el saldo de address, BlockNumberes el bloque real que desea buscar y la función vacía es una función de devolución de llamada (algunas implementaciones de web3 como MetaMask las necesitan))

(Consulte: https://github.com/ethereum/wiki/wiki/JavaScript-API en Métodos de contrato)

Esta es exactamente mi pregunta. Cuando llamo ERC20Contract.balanceOf(address, BlockNumber, function(){}), no importa lo que BlockNumberespecifique, siempre obtengo el mismo número: el último saldo. Mi entorno de prueba es Ganache + geth + javascript web3.
¿Qué versión de web3 estás usando?
Realmente aprecio su paciencia. He editado la pregunta. En realidad, no estoy usando nodejs, estoy usando geth 1.8.2-stable.
Realmente no conozco la sintaxis geth, pero debería ser la misma. Verifique su documentación sobre a qué bloque se conectan.