En este primer capítulo intentaré explicar los desafíos:
1. Guess the number2. Guess the secret number
3. Guess the random number
1. Guess the number
Problema:
"Estoy pensando en un número. Todo lo que tienes que hacer es adivinarlo."El contrato que atacaremos será el siguiente
pragma solidity ^0.4.21;
contract GuessTheNumberChallenge {
uint8 answer = 42;
function GuessTheNumberChallenge() public payable {
require(msg.value == 1 ether);
}
function isComplete() public view returns (bool) {
return address(this).balance == 0;
}
function guess(uint8 n) public payable {
require(msg.value == 1 ether);
if (n == answer) {
msg.sender.transfer(2 ether);
}
}
}
Datos de lectura:
Ideas para soluciones:
Explicación:
Test a ejecutar:
Conclusión:
Leer código es SÚPER importante. Así, muchas veces encontraremos cosas que los desarrolladores olvidaron borrar o simplemente pensaron que no habría problema alguno en dejarlo ahí, a nuestro alcance. Conoce a tu enemigo y esas cosas, vos me entendés…
2. Guess the secret number
Problema:
"Esta vez solo guardé el hash del número. Buena suerte reverseando el hash criptográfico!"El contrato que atacaremos será el siguiente
pragma solidity ^0.4.21;
contract GuessTheSecretNumberChallenge {
bytes32 answerHash = 0xdb81b4d58595fbbbb592d3661a34cdca14d7ab379441400cbfa1b78bc447c365;
function GuessTheSecretNumberChallenge() public payable {
require(msg.value == 1 ether);
}
function isComplete() public view returns (bool) {
return address(this).balance == 0;
}
function guess(uint8 n) public payable {
require(msg.value == 1 ether);
if (keccak256(n) == answerHash) {
msg.sender.transfer(2 ether);
}
}
}
Datos de lectura:
Ideas para soluciones:
Explicación:
Test a ejecutar:
Conclusión:
Siempre es interesante recordar que un atacante dispone de 2 cosas: tiempo y recursos infinitos. Pretender que una entrada “n” es imposible de hallar, cuando se comparte públicamente en la blockchain la lógica que aplicamos, es subestimar esos 2 elementos mencionados anteriormente.
3. Guess the random number
Problema:
"Esta vez el número es generado basándose en un par de fuentes bastante aleatorias."El contrato que atacaremos será el siguiente
pragma solidity ^0.4.21;
contract GuessTheRandomNumberChallenge {
uint8 answer;
function GuessTheRandomNumberChallenge() public payable {
require(msg.value == 1 ether);
answer = uint8(keccak256(block.blockhash(block.number - 1), now));
}
function isComplete() public view returns (bool) {
return address(this).balance == 0;
}
function guess(uint8 n) public payable {
require(msg.value == 1 ether);
if (n == answer) {
msg.sender.transfer(2 ether);
}
}
}
Datos de lectura:
Ideas para soluciones:
Explicación:
Test a ejecutar:
Conclusión:
Existen 3 tipos de visibilidad para las variables: public, internal y private. Sin embargo, cuando hablamos de esta visibilidad, nos estamos refiriendo a si otro contrato puede o no ver su contenido. Fuera de los contratos, cualquier persona puede analizar el estado del contrato, desde etherscan por ejemplo, y encontrar el valor actual de cierta variable. Todo es público y transparente, por eso amamos la web 3.0 😎