Puzzle 4

ADDRESS, BALANCE

Puzzle

############
# Puzzle 4 #
############

00      30        ADDRESS
01      31        BALANCE
02      36        CALLDATASIZE
03      6000      PUSH1 00
05      6000      PUSH1 00
07      37        CALLDATACOPY
08      36        CALLDATASIZE
09      6000      PUSH1 00
0B      30        ADDRESS
0C      31        BALANCE
0D      F0        CREATE
0E      31        BALANCE
0F      90        SWAP1
10      04        DIV
11      6002      PUSH1 02
13      14        EQ
14      6018      PUSH1 18
16      57        JUMPI
17      FD        REVERT
18      5B        JUMPDEST
19      00        STOP

? Enter the value to send: (0) 

Solution

This combo:

ADDRESS
BALANCE

is equivalent to:

address(this).balance

Pseudocode:

// Copy calldata to memory offset 0
calldatacopy(0, 0, calldata_size);

// Create a new contract and give it all the balance of the current contract
create(address(this).balance, 0x00, calldata_size);

if (old_contract_balance / new_contract_balance == 2) {
    jump(0x18);
}

The new contract must burn half of the balance it receives. For example, if the challenge contract has 8 wei, then 4 wei is sent to the new contract when create() is called. Once received, the new contract must burn 4 wei so that 8 wei / 4 wei == 2.

Burning half of the balance is equivalent to sending them to the zero address. Suppose we are sending 8 wei as msg.value, then we need to burn 4 wei in the new contract. This can be done with CALL:

PUSH1 0x00 // retSize
DUP1 // retOffset
DUP1 // argsSize
DUP1 // argsOffset
PUSH1 0x04 // value
DUP2 // address
GAS // gas
CALL

PUSH1 0x00
DUP1
RETURN

We are not returning anything because nothing needs to be returned, but the RETURN part of the code is needed to terminate the contract.

Compile:

60008080806004815af1600080f3

Last updated