¿Cuál es la mejor manera de distribuir tokens?

Si creo un token y luego quiero distribuirlo a 1000 personas, me preocupa el precio del combustible de esas transacciones. Por eso quería analizar las diferentes opciones de distribución y sus costos inherentes.

opción 1: función en token que distribuye a una matriz de usuarios

function distributeToken(address[] addresses, uint256 _value) onlyOwner {
     for (uint i = 0; i < addresses.length; i++) {
         balances[owner] -= _value;
         balances[addresses[i]] += _value;
         Transfer(owner, addresses[i], _value);
     }
}

fuente: distribuir token a múltiples direcciones

ELABORACIÓN DE LA OPCIÓN UNO: ¿es posible usar parámetros con una matriz de 1000 direcciones diferentes? Ese sería un parámetro enormemente grande y tengo curiosidad por saber cómo sería el precio del gas.

opción 2: usar un intercambio

Sin embargo, esta opción es muy restrictiva. Permitiría que cualquier persona compre las monedas, y no necesariamente quiero que se compren, sino que se regalen de forma gratuita a usuarios específicos.

PREGUNTAS

  • ¿Hay otras opciones que la gente conozca?
  • ¿Qué opción sería la más adecuada y costaría la menor cantidad de gass?

DIFERENCIAS ENTRE LA PREGUNTA DUPLICADA ENLAZADA Y ESTA: ( ¿Cómo transferir tokens a los participantes de recompensas? )

Las preguntas tienen diferencias notables.

  • Los detalles que se están discutiendo.
  • También tengo 2 preguntas específicas al final que no son idénticas a esa

mientras que la pregunta vinculada que es similar pregunta:

  • ¿Cuál es la mejor práctica para enviar tokens compatibles con ERC20 a los participantes de recompensas?

No proporciona los criterios específicos de lo que mejor se referiría, mientras que yo sí, y también pido las otras opciones disponibles para hacer una comparación. Aunque tienen similitudes, no son lo mismo.

@ElishaDrion Gracias por el enlace, aunque creo que las preguntas tienen diferencias notables, la principal es sobre los detalles que se están discutiendo. También tengo 2 preguntas específicas al final que no son idénticas a esa pregunta. Aunque son similares, no son lo mismo.

Respuestas (1)

La mejor manera

La mejor manera es un término bastante objetivo.

La forma más rentable es definitivamente ejecutarlos todos en un ciclo (opción 1), aunque habrá un límite en la cantidad de direcciones que puede ejecutar a la vez (probablemente necesitará hacer 10 lotes de 100 direcciones cada uno).

La opción 2 puede costarle indirectamente menos en gasolina, pero alguien aún tiene que pagar la gasolina, y dado que (presuntamente) ejecutarán una por una, el costo total de la gasolina será mayor, pero como usted no la pagará, tal vez eso es mejor para ti?

Una implementación ligeramente mejor:

function distributeToken(address[] addresses, uint256 _value) onlyOwner {
     uint total = _value * addresses.length;
     require(total/_value == addresses.length); // Overflow check
     require(balances[owner] >= total); // Underflow check
     balances[owner] -= total;
     for (uint i = 0; i < addresses.length; i++) {
         balances[addresses[i]] += _value;
         require(balances[addresses[i]] >= _value); // Overflow check
         Transfer(owner, addresses[i], _value);
     }
}

Estimaciones de gas:

Para llamadas individuales a una función típica transfer(), es el mismo costo por llamada, lo que significa que por cada dirección estarás pagando 23.500 de gasolina.

Sin embargo, cuando realiza una actualización masiva, ahorra la sobrecarga del costo de la invocación y solo tiene que pagar el costo del bucle y el almacenamiento, etc. Después de un costo base de 27,947 gas, cada dirección solo cuesta 9,703 gas adicionales.

┌─────┬────────────┬─────────────────┐
│ # │ transferir │ distribuirToken │
├─────┼────────────┼─────────────────┤
│ 1 │ 23 500 │ 37 650 │
│ 2 │ 47 000 │ 47 353 │
│ 3 │ 70 500 │ 57 056 │
│ 10 │ 235.000 │ 124.977 │
│ 50 │ 1.175.000 │ 513.097 │
│ 500 │ 11.750.000 │ 4.879.447 │
└─────┴────────────┴─────────────────┘

Eso significa que después de 2 direcciones es más barato.

Por 8 Mgas (máximo para una sola llamada), podría hacer alrededor de 821 direcciones:

27,947 base call gas + 9,703 gas/address * 821 addresses = 7,994,110 gas
¿Por qué no usar la transferfunción del token, además de las JUMPinstrucciones de ahorro?
En general, las funciones de airdrop tienden a querer ser lo más eficientes posible. Llamar a la función de transferencia también suele ser una función pública que es un poco más costosa que saltar a una función de transferencia interna, pero administrarla dentro de una sola función incluso ahorra ese costo.
muy interesante, me pregunto cuánta diferencia en el gas traería esto. Por ejemplo si enviar a 100 personas con la distributeTokenfunción cuesta lo mismo que enviar a 2 personas a través de la transferfunción ERC-20
Hay un costo mínimo de 21 000 de gasolina por llamada, por lo que incluso con un costo mínimo absoluto (excluyendo costos de almacenamiento, etc.), 2 llamadas a transfer() costarían 42 000 de gasolina.
Sí, me di cuenta de eso, pero me pregunto si las diferencias son tan grandes, si vale la pena repetir el código.
Solo como una idea, hacerlo de esta manera (llamar transfer()en lugar de codificarlo en el bucle) daría como resultado un costo base más económico de 22 239, pero cada dirección agregaría 13 978 gasolina/dirección, por lo que: 1 dirección = 36 117; 2 = 50.095; 3 = 64.073 y así sucesivamente.
Sin embargo, para ser justos, reducir la huella del código ahorraría 75 539 de gasolina en la creación, por lo que debe tenerse en cuenta. Con 1000 direcciones, los ahorros en el bucle combinado serían de 4 275 000, lo que significa que estaría por delante en aproximadamente 4,2 Mgas.
muchas gracias hombre, realmente pusiste muchos detalles en tu respuesta, realmente lo aprecio
¿Puedo preguntar cómo encontraste los valores base? ¿Fue a través de pruebas a través de remixes? y si es así, ¿tendría alguna guía o enlace a tutoriales que puedan mostrar el proceso?
Simplemente coloque el código en la remezcla y haga clic en el botón "Detalles" cuando ejecute las funciones. El número que está buscando es transaction costcuál es el costo real de ejecutar la llamada. Luego, simplemente copie ese número e intente una forma diferente, luego las matemáticas simples le dirán si la nueva forma es mejor o peor.