¿Por qué uint8 cuesta más gasolina que uint256?

contract A {
  uint8 a = 0;
}

cuesta 20150 + 2000 de gas durante la creación.

en comparación con

contract A {
  uint a = 0;   // or uint256
}

costando 5050 + 2000 de gas durante la creación

Es extraño que una variable que ocupa menos espacio de almacenamiento cueste más gasolina. ¿Por qué es así?

Respuestas (4)

El EVM funciona con palabras de 256 bits/32 bytes (decisión de diseño discutible). Cada operación se basa en estas unidades base. Si sus datos son más pequeños, se necesitan más operaciones para reducir la escala de 256 bits a 8 bits, por lo que verá un aumento de los costos.

Por cierto, si cambia los "Detalles" en el compilador de solidez en línea, le dará el volcado de ensamblaje exacto de donde provienen los códigos de operación adicionales. No tuve tiempo ahora para interpretarlos, pero si lo hace y descubre que hay algo adicional, estoy seguro de que el equipo de Solidity estará feliz de agregar optimizaciones para solucionarlos.

Sí, vi las instrucciones de montaje. Iba a examinarlo más a fondo si no podía obtener ninguna respuesta aquí. Gracias por su respuesta. Es una decisión extraña para empezar uint256. Siguiente pregunta Me pregunto si entonces siempre tiene sentido apegarse a uint256 y nunca más pequeño.
@uzyn Usar valores más pequeños para el almacenamiento tiene sentido, porque escribir en el almacenamiento es costoso y el compilador empaquetará múltiples argumentos más pequeños. Para parámetros de función y variables de memoria, solo tiene sentido si desea restringir el rango de valores: no hay empaque, por lo que no es ni más ni menos costoso.
Cuando creamos una variable como uint32dentro de a en structlugar de uint256y la insertamos en una matriz, cuesta mucho menos gasolina.

Sin embargo, debe tenerse en cuenta que en una estructura, uint8 SÍ cuesta menos que un uint tradicional, debido a la función de empaquetado ajustado. También asegúrese de que sus unidades estén junto a sus otras unidades, y bytes junto a bytes, etc. Esto aumenta aún más las características compactas.

¿Qué quiere decir con "asegúrese de que sus unidades estén junto a sus otras unidades, y bytes junto a bytes, etc...."? Entonces, en un structdebería uintsdefinirse uno tras otro en otros tipos también y ¿por qué? @VoR0220
Recomienda esto porque el orden en que declara sus variables de estado puede afectar la cantidad total de espacios de almacenamiento que utiliza su contrato. Si declara 2 uint128 y luego un uin256, usará 2 ranuras de almacenamiento de 256 bits; 1 ranura para 2 uint128 y 1 ranura para uint256. Si declara 1 uint128, luego uint256, luego uint128, su contrato usará 3 ranuras de almacenamiento, porque no puede ajustar la variable de estado uint256 del medio en una ranura de almacenamiento con cualquiera de los uint128, por lo que cada variable deberá tener su propia ranura de almacenamiento.

SOLC 0.4.18: ahora la diferencia es pequeña

https://ethfiddle.com/6lt852gx7K

Contrato A usando uint8costos 75414 para implementar

Contrato B usando uint256costos 73867 para implementar

Una diferencia de 1547 gas.

sigue siendo cierto en las versiones más recientes de solidity (los mismos costos exactos para 0.6.11 y 0.7.1)
En solidity 0.8.10 es alrededor de 100 unidades más costosas de gas8 que uint256 para implementar.

Actualización en diciembre de 2021:

Si prueba algo como esto: 5 variables en lugar de solo 1, lo que podría parecerse más a un escenario del mundo real con múltiples variables, no solo una.

contract A {
  uint8 a = 0;
  uint8 b = 0;
  uint8 c = 0;
  uint8 d = 0;
  uint8 e = 0;
}

Entonces es más barato que su versión uint256.

De la remezcla:

uint8: 69484gas uint256: 78420gas

Actualización junio 2022 (0.8.15)

uint8: 83524gas uint256: 90183gas

Entonces, ahorra en gasolina usando uint de menor tamaño, como dicen otros comentarios, si esos son arreglos, ahorra más.