✅Predictable NFT
Idea
Go to the contract address and decompile the bytecode:
# Palkeoramix decompiler.
def storage:
id is uint256 at storage 0
tokens is mapping of uint256 at storage 1
def tokens(uint256 _param1): # not payable
require calldata.size - 4 >=′ 32
return tokens[_param1]
def id(): # not payable
return id
#
# Regular functions
#
def _fallback() payable: # default function
revert
def mint() payable:
if call.value != 10^18:
revert with 0, 'show me the money'
if id > id + 1:
revert with 0, 17
id++
if sha3(id, caller, block.number) % 100 > 90:
tokens[stor0] = 3
else:
if sha3(id, caller, block.number) % 100 <= 80:
tokens[stor0] = 1
else:
tokens[stor0] = 2
return id
Here tokens[stor0]
is the rank of the NFT minted. tokens[stor0] = 3
means "Superior" and that is what we want. Therefore the key to this chall is handle sha3(id, caller, block.number) % 100 > 90
.
Recall that block.number
can't be used for the source of randomness because this information will stay the same if we recompute it within the same tx. There are two subtle details:
id++
happens beforesha3()
, be aware of that.We can't see if
encode()
orencodePacked()
is used by the original contract, so try both.
PoC
Last updated