Mi problema es que necesito asegurarme de que mi contrato procese solo las transacciones provenientes de EOA (cuentas de propiedad externa). Para esto necesito determinar el tipo de cuenta con la que estoy tratando. En esta pregunta encontré una solución, aquí está el código:
function isContract(address addr) returns (bool) {
uint size;
assembly { size := extcodesize(addr) }
return size > 0;
}
Como no entiendo el ensamblaje en absoluto, no tengo idea de lo que está pasando allí.
¡Gracias!
EDITAR: la función devolverá falso si se invoca desde el constructor de un contrato (porque el contrato aún no se ha implementado).
El código debe usarse con mucho cuidado, si es que se usa, para evitar ataques de seguridad como:
https://www.reddit.com/r/ethereum/comments/916xni/how_to_pwn_fomo3d_a_beginners_guide/ ( archivo )
Para repetir :
No utilice la verificación EXTCODESIZE para evitar que los contratos inteligentes llamen a una función. Esto no es infalible, puede ser subvertido por una llamada de constructor, debido al hecho de que mientras el constructor se está ejecutando, EXTCODESIZE para esa dirección devuelve 0.
Consulte el código de muestra de un contrato que engaña a EXTCODESIZE para que devuelva 0.
Si desea asegurarse de que una cuenta de propiedad externa (EOA) está llamando a su contrato, una forma sencilla es require(msg.sender == tx.origin)
. Sin embargo, impedir un contrato es un antipatrón con consideraciones de seguridad e interoperabilidad .
Esto deberá revisarse cuando se implemente la abstracción de cuenta.
Respuesta previa.
Sí, la función funciona.
EXTCODESIZE es el código de operación EVM para obtener el tamaño del código en una dirección.
0x3b EXTCODESIZE Obtener el tamaño del código de una cuenta
Un contrato no puede engañar a EXTCODESIZE para que devuelva cero para el tamaño del contrato.
Además, una cuenta de propiedad externa (EOA) no puede engañar a este código para que piense que la EOA es un contrato. Esto se debe a que un EOA no tiene código (longitud cero) y no es más factible poner código en un EOA que encontrar la clave privada de un contrato.
La función no tiene ninguna dependencia de Prueba de participación y seguirá funcionando.
extcodesize
pronto devolverá valores distintos de cero para lo que alguna vez fueron cuentas externas, necesito evitar este atajo.Este fragmento de código es correcto, aunque parece importante tener en cuenta que EXTCODESIZE
devolverá 0 cuando se llame dentro constructor
de un contrato, ya que el contrato aún no se ha creado. Por lo tanto, si msg.sender
es un contrato, el isContract()
modificador podría devolver falso si la función de su contrato se llama dentro del constructor del msg.sender
contrato. Este vector de ataque se ha utilizado en varias ocasiones, como drenar el "cazo aéreo" ETH de FoMo3D .
Una solución a esto sería (A) requerir msg.sender
que proporcione una firma ECDSA para su primera llamada de función, (B) msg.sender
solicitar que llame a su contrato en dos bloques separados o (C) agregar require(msg.sender == tx.origin)
. Este último sería el más económico, seguido de ECDSA y el más costoso sería el proceso de 2 pasos.
ética
ética