If you wanna dig deeper at the Ethereum Virtual Machine level, those are some resources to start:

EthTx Transaction Decoder https://ethtx.info/

Ethereum Signature Database https://www.4byte.directory/

Ethereum JSON-RPC API https://ethereum.org/es/developers/docs/apis/json-rpc/#eth_call

Ethereum Virtual Machine Opcodes https://ethervm.io/

Solidity compiler EVM and OPCodes

Let’s try with the following vulnerable (do not use!) smart contract:

// Filename: target.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

// THIS CONTRACT CONTAINS A BUG - DO NOT USE

contract TxUserWallet {
    address owner;

    constructor() {
        owner = msg.sender;
    }

    function transferTo(address payable dest, uint amount) public {
        // THE BUG IS RIGHT HERE, you must use msg.sender instead of tx.origin
        require(tx.origin == owner);
        dest.transfer(amount);
    }
}

Opcodes of the contract:

solc --opcodes target.sol
======= target.sol:TxUserWallet =======
Opcodes:
PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLER PUSH1 0x0 DUP1 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP PUSH2 0x1FE DUP1 PUSH2 0x60 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x2B JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x2CCB1B30 EQ PUSH2 0x30 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x4A PUSH1 0x4 DUP1 CALLDATASIZE SUB DUP2 ADD SWAP1 PUSH2 0x45 SWAP2 SWAP1 PUSH2 0x188 JUMP JUMPDEST PUSH2 0x4C JUMP JUMPDEST STOP JUMPDEST PUSH1 0x0 DUP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND ORIGIN PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ PUSH2 0xA4 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x8FC DUP3 SWAP1 DUP2 ISZERO MUL SWAP1 PUSH1 0x40 MLOAD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP9 DUP9 CALL SWAP4 POP POP POP POP ISZERO DUP1 ISZERO PUSH2 0xEA JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x11F DUP3 PUSH2 0xF4 JUMP JUMPDEST SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x12F DUP2 PUSH2 0x114 JUMP JUMPDEST DUP2 EQ PUSH2 0x13A JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP2 CALLDATALOAD SWAP1 POP PUSH2 0x14C DUP2 PUSH2 0x126 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x165 DUP2 PUSH2 0x152 JUMP JUMPDEST DUP2 EQ PUSH2 0x170 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP2 CALLDATALOAD SWAP1 POP PUSH2 0x182 DUP2 PUSH2 0x15C JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x19F JUMPI PUSH2 0x19E PUSH2 0xEF JUMP JUMPDEST JUMPDEST PUSH1 0x0 PUSH2 0x1AD DUP6 DUP3 DUP7 ADD PUSH2 0x13D JUMP JUMPDEST SWAP3 POP POP PUSH1 0x20 PUSH2 0x1BE DUP6 DUP3 DUP7 ADD PUSH2 0x173 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 SWAP1 POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 SELFDESTRUCT DUP12 0x5C DUP12 LOG3 PUSH31 0xF051A68ED77F5F39AD93423518F814BD59C16C9D1C94948A358C64736F6C63 NUMBER STOP ADDMOD LT STOP CALLER

EVM assembly of the contract:

solc --asm target.sol
======= target.sol:TxUserWallet =======
EVM assembly:
    /* "target.sol":116:449  contract TxUserWallet {... */
  mstore(0x40, 0x80)
    /* "target.sol":167:218  constructor() {... */
  callvalue
  dup1
  iszero
  tag_1
  jumpi
  0x00
  dup1
  revert
tag_1:
  pop
    /* "target.sol":200:210  msg.sender */
  caller
    /* "target.sol":192:197  owner */
  0x00
  dup1
    /* "target.sol":192:210  owner = msg.sender */
  0x0100
  exp
  dup2
  sload
  dup2
  0xffffffffffffffffffffffffffffffffffffffff
  mul
  not
  and
  swap1
  dup4
  0xffffffffffffffffffffffffffffffffffffffff
  and
  mul
  or
  swap1
  sstore
  pop
    /* "target.sol":116:449  contract TxUserWallet {... */
  dataSize(sub_0)
  dup1
  dataOffset(sub_0)
  0x00
  codecopy
  0x00
  return
stop

sub_0: assembly {
        /* "target.sol":116:449  contract TxUserWallet {... */
      mstore(0x40, 0x80)
      callvalue
      dup1
      iszero
      tag_1
      jumpi
      0x00
      dup1
      revert
    tag_1:
      pop
      jumpi(tag_2, lt(calldatasize, 0x04))
      shr(0xe0, calldataload(0x00))
      dup1
      0x2ccb1b30
      eq
      tag_3
      jumpi
    tag_2:
      0x00
      dup1
      revert
        /* "target.sol":226:446  function transferTo(address payable dest, uint amount) public {... */
    tag_3:
      tag_4
      0x04
      dup1
      calldatasize
      sub
      dup2
      add
      swap1
      tag_5
      swap2
      swap1
      tag_6
      jump	// in
    tag_5:
      tag_7
      jump	// in
    tag_4:
      stop
    tag_7:
        /* "target.sol":400:405  owner */
      0x00
      dup1
      sload
      swap1
      0x0100
      exp
      swap1
      div
      0xffffffffffffffffffffffffffffffffffffffff
      and
        /* "target.sol":387:405  tx.origin == owner */
      0xffffffffffffffffffffffffffffffffffffffff
      and
        /* "target.sol":387:396  tx.origin */
      origin
        /* "target.sol":387:405  tx.origin == owner */
      0xffffffffffffffffffffffffffffffffffffffff
      and
      eq
        /* "target.sol":379:406  require(tx.origin == owner) */
      tag_9
      jumpi
      0x00
      dup1
      revert
    tag_9:
        /* "target.sol":417:421  dest */
      dup2
        /* "target.sol":417:430  dest.transfer */
      0xffffffffffffffffffffffffffffffffffffffff
      and
        /* "target.sol":417:438  dest.transfer(amount) */
      0x08fc
        /* "target.sol":431:437  amount */
      dup3
        /* "target.sol":417:438  dest.transfer(amount) */
      swap1
      dup2
      iszero
      mul
      swap1
      mload(0x40)
      0x00
      mload(0x40)
      dup1
      dup4
      sub
      dup2
      dup6
      dup9
      dup9
      call
      swap4
      pop
      pop
      pop
      pop
      iszero
      dup1
      iszero
      tag_11
      jumpi
      returndatasize
      0x00
      dup1
      returndatacopy
      revert(0x00, returndatasize)
    tag_11:
      pop
        /* "target.sol":226:446  function transferTo(address payable dest, uint amount) public {... */
      pop
      pop
      jump	// out
        /* "#utility.yul":88:205   */
    tag_13:
        /* "#utility.yul":197:198   */
      0x00
        /* "#utility.yul":194:195   */
      dup1
        /* "#utility.yul":187:199   */
      revert
        /* "#utility.yul":334:460   */
    tag_15:
        /* "#utility.yul":371:378   */
      0x00
        /* "#utility.yul":411:453   */
      0xffffffffffffffffffffffffffffffffffffffff
        /* "#utility.yul":404:409   */
      dup3
        /* "#utility.yul":400:454   */
      and
        /* "#utility.yul":389:454   */
      swap1
      pop
        /* "#utility.yul":334:460   */
      swap2
      swap1
      pop
      jump	// out
        /* "#utility.yul":466:570   */
    tag_16:
        /* "#utility.yul":511:518   */
      0x00
        /* "#utility.yul":540:564   */
      tag_28
        /* "#utility.yul":558:563   */
      dup3
        /* "#utility.yul":540:564   */
      tag_15
      jump	// in
    tag_28:
        /* "#utility.yul":529:564   */
      swap1
      pop
        /* "#utility.yul":466:570   */
      swap2
      swap1
      pop
      jump	// out
        /* "#utility.yul":576:714   */
    tag_17:
        /* "#utility.yul":657:689   */
      tag_30
        /* "#utility.yul":683:688   */
      dup2
        /* "#utility.yul":657:689   */
      tag_16
      jump	// in
    tag_30:
        /* "#utility.yul":650:655   */
      dup2
        /* "#utility.yul":647:690   */
      eq
        /* "#utility.yul":637:708   */
      tag_31
      jumpi
        /* "#utility.yul":704:705   */
      0x00
        /* "#utility.yul":701:702   */
      dup1
        /* "#utility.yul":694:706   */
      revert
        /* "#utility.yul":637:708   */
    tag_31:
        /* "#utility.yul":576:714   */
      pop
      jump	// out
        /* "#utility.yul":720:875   */
    tag_18:
        /* "#utility.yul":774:779   */
      0x00
        /* "#utility.yul":812:818   */
      dup2
        /* "#utility.yul":799:819   */
      calldataload
        /* "#utility.yul":790:819   */
      swap1
      pop
        /* "#utility.yul":828:869   */
      tag_33
        /* "#utility.yul":863:868   */
      dup2
        /* "#utility.yul":828:869   */
      tag_17
      jump	// in
    tag_33:
        /* "#utility.yul":720:875   */
      swap3
      swap2
      pop
      pop
      jump	// out
        /* "#utility.yul":881:958   */
    tag_19:
        /* "#utility.yul":918:925   */
      0x00
        /* "#utility.yul":947:952   */
      dup2
        /* "#utility.yul":936:952   */
      swap1
      pop
        /* "#utility.yul":881:958   */
      swap2
      swap1
      pop
      jump	// out
        /* "#utility.yul":964:1086   */
    tag_20:
        /* "#utility.yul":1037:1061   */
      tag_36
        /* "#utility.yul":1055:1060   */
      dup2
        /* "#utility.yul":1037:1061   */
      tag_19
      jump	// in
    tag_36:
        /* "#utility.yul":1030:1035   */
      dup2
        /* "#utility.yul":1027:1062   */
      eq
        /* "#utility.yul":1017:1080   */
      tag_37
      jumpi
        /* "#utility.yul":1076:1077   */
      0x00
        /* "#utility.yul":1073:1074   */
      dup1
        /* "#utility.yul":1066:1078   */
      revert
        /* "#utility.yul":1017:1080   */
    tag_37:
        /* "#utility.yul":964:1086   */
      pop
      jump	// out
        /* "#utility.yul":1092:1231   */
    tag_21:
        /* "#utility.yul":1138:1143   */
      0x00
        /* "#utility.yul":1176:1182   */
      dup2
        /* "#utility.yul":1163:1183   */
      calldataload
        /* "#utility.yul":1154:1183   */
      swap1
      pop
        /* "#utility.yul":1192:1225   */
      tag_39
        /* "#utility.yul":1219:1224   */
      dup2
        /* "#utility.yul":1192:1225   */
      tag_20
      jump	// in
    tag_39:
        /* "#utility.yul":1092:1231   */
      swap3
      swap2
      pop
      pop
      jump	// out
        /* "#utility.yul":1237:1727   */
    tag_6:
        /* "#utility.yul":1313:1319   */
      0x00
        /* "#utility.yul":1321:1327   */
      dup1
        /* "#utility.yul":1370:1372   */
      0x40
        /* "#utility.yul":1358:1367   */
      dup4
        /* "#utility.yul":1349:1356   */
      dup6
        /* "#utility.yul":1345:1368   */
      sub
        /* "#utility.yul":1341:1373   */
      slt
        /* "#utility.yul":1338:1457   */
      iszero
      tag_41
      jumpi
        /* "#utility.yul":1376:1455   */
      tag_42
      tag_13
      jump	// in
    tag_42:
        /* "#utility.yul":1338:1457   */
    tag_41:
        /* "#utility.yul":1496:1497   */
      0x00
        /* "#utility.yul":1521:1582   */
      tag_43
        /* "#utility.yul":1574:1581   */
      dup6
        /* "#utility.yul":1565:1571   */
      dup3
        /* "#utility.yul":1554:1563   */
      dup7
        /* "#utility.yul":1550:1572   */
      add
        /* "#utility.yul":1521:1582   */
      tag_18
      jump	// in
    tag_43:
        /* "#utility.yul":1511:1582   */
      swap3
      pop
        /* "#utility.yul":1467:1592   */
      pop
        /* "#utility.yul":1631:1633   */
      0x20
        /* "#utility.yul":1657:1710   */
      tag_44
        /* "#utility.yul":1702:1709   */
      dup6
        /* "#utility.yul":1693:1699   */
      dup3
        /* "#utility.yul":1682:1691   */
      dup7
        /* "#utility.yul":1678:1700   */
      add
        /* "#utility.yul":1657:1710   */
      tag_21
      jump	// in
    tag_44:
        /* "#utility.yul":1647:1710   */
      swap2
      pop
        /* "#utility.yul":1602:1720   */
      pop
        /* "#utility.yul":1237:1727   */
      swap3
      pop
      swap3
      swap1
      pop
      jump	// out

    auxdata: 0xa2646970667358221220ff8b5c8ba37ef051a68ed77f5f39ad93423518f814bd59c16c9d1c94948a358c64736f6c63430008100033
}

How useful was this post?

Click on a star to rate it!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Leave a Reply