1

I'm trying to understand why the following toy contract does not work. I can deploy it successfully, and transactions with fewer than 36 bytes of data are successful, but those containing 36 bytes or more fail. I would expect that no failures would exist for any input size.

{
  codecopy(0x0, 0x0, codesize())
  return(0xD, sub(codesize(), 0xD))

  if lt(calldatasize(), 0x24) {
    stop
  }

  if lt(calldatasize(), 0x84) {
    stop
  }

  stop
}

Bytecode: 386000600039600d3803600df36024361015601657005b6084361015602057005b00

| improve this question | | | | |
0

The problem is that in your deployed/run-time byte code the jump destinations are wrong. I don't think the assembler is expecting to find a constructor in there, and so it doesn't account for the 13 byte shift in the jump destinations.

This is the run-time dissasembly. You can see that the jumps are 0xd off.

0000  PUSH1 0x24
0002  CALLDATASIZE
0003  LT
0004  ISZERO
0005  PUSH1 0x16  <-- should be 0x09
0007  JUMPI

0008  STOP

0009  JUMPDEST
000a  PUSH1 0x84
000c  CALLDATASIZE
000d  LT
000e  ISZERO
000f  PUSH1 0x20  <-- should be 0x13
0011  JUMPI

0012  STOP

0013  JUMPDEST
0014  STOP

If you want to explore this kind of thing, I recommend LLL. The LLL compiler is available when you build Solidity from source. The LLL equivalent of your contract is as follows:

(returnlll
  (seq
    (when (lt (calldatasize) 0x24) (stop))
    (when (lt (calldatasize) 0x84) (stop))
    (stop)))

The returnlll expression above is a macro that takes into account the constructor/deployment code when invoking the compiler, so this problem does not occur.

You can find LLL documentation here.

| improve this answer | | | | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.