So you found a compiler bug

How to find the affected parties and responsibly disclose it

vyper
data
Author

banteg

Published

September 2, 2023

Today I will walk you through the development of a pipeline that helps Vyper devs identify potentially vulnerable contracts, following a real compiler bug disclosure1. We will find all contracts that use certain opcodes and precompiles.

The pipeline would consist of the following steps:

  1. Find all Vyper contracts
  2. Strip them down to their code section
  3. Look for patterns in opcodes
  4. Contact the affected protocols

You can also reference this post for how the compiler signature, the immutable support, and the init code have changed over the development of Vyper.

Stripping metadata

Smart contracts on Ethereum can mix code and data sections. To accurately assess the opcodes used by a contract it is crucial to only look at the executable section. We would need to find a way to ignore the metadata, immutables or any other non-code portions of the runtime code that might result in false positives when interpreted as opcodes.

This section’s goal is to determine the total size of immutables so we can strip them.

Vyper compiler signature

Since 0.3.4 Vyper appends a compiler signature2 with the compiler name and 3 version bytes at the very end of the code output.

cbor.loads(b"\xa1\x65vyper\x83\x00\x03\x09")
{'vyper': [0, 3, 9]}

Since 0.3.5 it also appends3 a two-byte length after it.

int(b"\x00\x0b".hex(), 16)
11

So far seems easy, we just read the offset and everything before it is code. But this method doesn’t account for immutables that come after the signature.

A more reliable method is to simply split on \xa1\x65vyper\x83 and treat everything after as a data section. The problem is, immutables were introduced4 in 0.3.1, before the compiler signature has existed.

Another problem is the signature will be removed5 from runtime code altogether in 0.3.10. There is an ongoing discussion6 about whether to keep it.

For older versions we could use some old but proven heuristics:

  • 6004361015 prefix detects all contracts written in Vyper 0.2.0 to 0.2.4 and 0.2.11 to 0.3.3
  • 341561000a prefix was used in versions 0.2.5 to 0.2.8

Load all Vypers

We use cryo contracts dataset7 to quickly find all contracts that look like Vyper.

  • 7 Run cryo contracts --align and wait about 10 hours

  • contracts = pl.scan_parquet("~/data/contracts/*.parquet")
    vyper_sig = b"\xa1\x65vyper\x83"
    vypers = contracts.filter(
        (
            pl.col("code").bin.starts_with(bytes.fromhex("6004361015"))
            | pl.col("code").bin.starts_with(bytes.fromhex("341561000a"))
            | pl.col("init_code").bin.contains(b"\xa1\x65vyper\x83")
        )
        & ~pl.col("code").bin.contains(b"\x64solc\x43")
    ).collect()
    
    len(vypers)
    3226

    Code within code

    Given the init code contains the runtime code, we can scan from where it starts and continue until it diverges or the init code runs out.

    def find_runtime_in_init(data):
        init_offset = data["init_code"].index(data["code"][:32])
        code_size = 0
    
        # zip terminates when the smallest iterable runs out
        for left, right in zip(data["init_code"][init_offset:], data["code"]):
            if left != right:
                break
            code_size += 1
    
        op = data["init_code"][init_offset - 1]
        return {
            "pre_opcode": opcodes.get(op, hex(op)),
            "init_offset": init_offset,
            "code_size": code_size,
            "runtime_size": len(data["code"]),
        }
    Apply and output
    results = (
        vypers.with_columns(
            search=pl.struct("init_code", "code").apply(find_runtime_in_init)
        )
        .unnest("search")
        .with_columns(data_size=pl.col("runtime_size") - pl.col("code_size"))
    )
    (
        results.select(
            ["pre_opcode", "init_offset", "code_size", "runtime_size", "data_size"]
        )
        .filter(pl.col("data_size") > 0)
        .sample(5)
    )
    shape: (5, 5)
    pre_opcode init_offset code_size runtime_size data_size
    str i64 i64 i64 i64
    "JUMP" 800 10439 10663 224
    "JUMP" 3049 19226 19290 64
    "JUMP" 67 394 458 64
    "JUMP" 749 23732 23892 160
    "RETURN" 835 3448 3480 32

    The sample shows the data doesn’t always align on the word size. It’s either correct or one byte smaller, fixable with a ceil rounding.

    results.groupby((pl.col("data_size") % 32).alias("remainder")).agg(pl.count())
    shape: (2, 2)
    remainder count
    i64 u32
    0 2889
    31 337

    Preceding opcode

    Now let’s look at common opcodes that come before the runtime code in the init code.

    results.groupby("pre_opcode").agg(pl.count()).sort("count", descending=True)
    shape: (5, 2)
    pre_opcode count
    str u32
    "JUMP" 2166
    "RETURN" 1057
    "0xad" 1
    "STOP" 1
    "0x28" 1

    The heuristic for finding old Vypers has caught some extra contracts.

    Vyper has historically only used JUMP and RETURN. Up to version 0.3.1, the runtime code is put in the middle with the init routine located near the end.

    In 0.3.2, when compile-time calculation of memory offsets for copying immutables 8 was introduced, the runtime code comes after the init code, right after RETURN that outputs it.

    By 0.3.10 all arguments to CODECOPY and RETURN became pre-computed values.

    Compare the init code below for other differences. The runtime section is shown with an indentation, the compiler signature is omitted.

    0000: PUSH1 0x20
    0002: PUSH2 0x82
    0005: PUSH1 0x80
    0007: CODECOPY
    0008: PUSH1 0x80
    000a: MLOAD
    000b: PUSH1 0xe0
    000d: MSTORE
    000e: PUSH2 0x5b
    0011: JUMP
        0012: PUSH1 0x4
        --snip--
        005a: REVERT
    005b: JUMPDEST
    005c: PUSH2 0x12
    005f: PUSH2 0x5b
    0062: SUB
    0063: PUSH2 0x12
    0066: PUSH2 0x100
    0069: CODECOPY
    006a: PUSH2 0x12
    006d: PUSH2 0x5b
    0070: SUB
    0071: PUSH1 0xe0
    0073: MLOAD
    0074: DUP2
    0075: PUSH2 0x100
    0078: ADD
    0079: MSTORE
    007a: DUP1
    007b: PUSH1 0x20
    007d: ADD
    007e: PUSH2 0x100
    0081: RETURN
    0000: PUSH1 0x20
    0002: PUSH2 0x6d
    0005: PUSH1 0x0
    0007: CODECOPY
    0008: PUSH1 0x0
    000a: MLOAD
    000b: PUSH4 0x44
    0010: MSTORE
    0011: PUSH2 0x44
    0014: PUSH2 0x29
    0017: PUSH4 0x0
    001c: CODECOPY
    001d: PUSH2 0x44
    0020: PUSH1 0x20
    0022: ADD
    0023: PUSH4 0x0
    0028: RETURN
        0029: PUSH1 0x4
        --snip--
        006c: REVERT
    0000: PUSH1 0x4a
    0002: MLOAD
    0003: POP
    0004: PUSH1 0x20
    0006: PUSH2 0x69
    0009: PUSH0
    000a: CODECOPY
    000b: PUSH0
    000c: MLOAD
    000d: PUSH1 0x4a
    000f: MSTORE
    0010: PUSH2 0x4a
    0013: PUSH2 0x1f
    0016: PUSH1 0x0
    0018: CODECOPY
    0019: PUSH2 0x6a
    001c: PUSH1 0x0
    001e: RETURN
        001f: PUSH1 0x3
        --snip--
        005b: REVERT

    Static analysis

    A small harness to run some code against all Vyper versions would be useful at this point. It will be our git bisect that will help us learn when a certain difference was introduced. Let’s work our way backwards from the latest version.

    0.3.10 - 0.3.8

    For 0.3.10 we can find something like PUSH1 0x86 MLOAD POP at the very beginning of the init code.

    It touches and then immediately discards a value, causing memory expansion 9 to 0x86 + 0x20 = 0xa6, which would be the resulting size of the returned runtime code.

  • 9 The memory allocation behavior happens since Vyper 0.3.8, see fix: uninitialized immutable values

  • Further on we can find PUSH2 0x066 PUSH2 0x04C PUSH1 0x0 CODECOPY, which translates to codecopy(dest_offset=0x0, mem_offset=0x4c, size=0x66). The size here is the size of the runtime code sans immutables. Thus we have 0xa6 - 0x66 = 0x40 or two words of immutables. If we terminate on the last CODECOPY before the first RETURN, we will get all the data we need.

    0.3.7 - 0.3.4

    These versions don’t have memory expansion at the beginning, but we can still grab the values from the hardcoded arguments to CODECOPY and RETURN:

    PUSH2 0x07F PUSH2 0x046 PUSH1 0x0 CODECOPY
    PUSH2 0x0BF PUSH1 0x0 RETURN

    These would translate to codecopy(dest_offset=0x0, mem_offset=0x46, size=0x7f) and return(mem_offset=0x0, size=0xbf). So the runtime code measures 0x7f bytes without data and the data section is 0xbf - 0x7f = 0x40 bytes long.

    0.3.3 - 0.3.2

    Same but the size argument to RETURN is not hardcoded.

    PUSH2 0x063 PUSH2 0x050 PUSH4 0x0000 CODECOPY
    PUSH2 0x063 PUSH1 0x40 ADD PUSH4 0x0000 RETURN

    0.3.1 and below

    This version has even more math going on. At this point I gave up and decided the easiest option would be to simply run the init code.

    PUSH2 0x037 PUSH2 0x0A0 SUB PUSH2 0x037 PUSH2 0x120 CODECOPY
    PUSH2 0x037 PUSH2 0x0A0 SUB PUSH1 0xE0 MLOAD
    DUP2 PUSH2 0x120 ADD MSTORE
    PUSH2 0x10 MLOAD
    DUP2 PUSH2 0x140 ADD MSTORE
    DUP1 PUSH1 0x40 ADD PUSH2 0x120 RETURN

    Execution path

    I wanted to try out the newly-released executable spec for Ethereum10, so I wrote a toy environment that can run the init code and grab the arguments to CODECOPY and RETURN from the stack.

    Prepare the environment
    from dataclasses import dataclass, asdict
    
    from ethereum.base_types import Bytes0
    from ethereum.shanghai.state import State, increment_nonce
    from ethereum.shanghai.utils.message import prepare_message
    from ethereum.shanghai.vm import Environment, Evm, Message, interpreter
    from ethereum.shanghai.vm.instructions import Ops
    from ethereum.shanghai.vm.stack import pop
    
    caller = bytes.fromhex("b00ba" * 8)
    
    
    def prepare_env():
        state = State()
        increment_nonce(state, caller)
        return Environment(
            caller, [], caller, bytes(20), 0, 0, 30_000_000, 0, 0, bytes(32), state, 1
        )
    
    
    def make_deploy_message(code):
        env = prepare_env()
        return prepare_message(caller, Bytes0(), 0, bytes.fromhex(code), 30_000_000, env)
    Init codes for a contract with immutables
    codes = {
        "0.3.10": "60865150346100485760206100bf5f395f516066527ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe60865261006661004c6000396100a66000f35b5f80fd5f3560e01c60026003820660011b61006001601e395f51565b630c55699c8118610058573461005c57602061006660403960206040f3610058565b63a56dfe4a8118610058573461005c57602061008660403960206040f35b5f5ffd5b5f80fd00580018003aa16576797065728300030a000b",
        "0.3.9": "60875150346100b05760206100b45f395f516067527ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe6087526100676100486000396100a76000f36003361161000c57610052565b5f3560e01c3461005657630c55699c81186100335760206100675f395f5160405260206040f35b63a56dfe4a81186100505760206100875f395f5160405260206040f35b505b5f5ffd5b5f80fda165767970657283000309000b005b5f80fd",
        "0.3.8": "60795150346100a25760206100a65f395f516059527ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe6079526100596100486000396100996000f35f3560e01c3461004857630c55699c81186100265760206100595f395f5160405260206040f35b63a56dfe4a81186100435760206100795f395f5160405260206040f35b505f5ffd5b5f80fda165767970657283000308000b005b5f80fd",
        "0.3.7": "346100c65760206100cb600039600051607f527ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe609f5261007f6100466000396100bf6000f36003361161000c57610067565b60003560e01c3461006d57630c55699c811861003e576004361061006d57602061007f60003960005160405260206040f35b63a56dfe4a8118610065576004361061006d57602061009f60003960005160405260206040f35b505b60006000fd5b600080fda165767970657283000307000b005b600080fd",
        "0.3.6": "346100c65760206100cb600039600051607f527ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe609f5261007f6100466000396100bf6000f36003361161000c57610067565b60003560e01c3461006d57630c55699c811861003e576004361861006d57602061007f60003960005160405260206040f35b63a56dfe4a8118610065576004361861006d57602061009f60003960005160405260206040f35b505b60006000fd5b600080fda165767970657283000306000b005b600080fd",
        "0.3.4": "346100c45760206100c9600039600051607d527ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe609d5261007d6100466000396100bd6000f36003361161000c57610067565b60003560e01c3461006d57630c55699c811861003e576004361861006d57602061007d60003960005160405260206040f35b63a56dfe4a8118610065576004361861006d57602061009d60003960005160405260206040f35b505b60006000fd5b600080fda165767970657283000304005b600080fd",
        "0.3.3": "60206100b36000396000516300000063527ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe6300000083526100636100506300000000396100636040016300000000f3600436101561000d57610058565b60003560e01c3461005e57630c55699c811861003757602061006360003960005160405260206040f35b63a56dfe4a811861005657602061008360003960005160405260206040f35b505b60006000fd5b600080fd",
        "0.3.2": "60206100b36000396000516300000063527ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe6300000083526100636100506300000000396100636040016300000000f3600436101561000d57610058565b60003560e01c3461005e57630c55699c811861003757602061006360003960005160405260206040f35b63a56dfe4a811861005657602061008360003960005160405260206040f35b505b60006000fd5b600080fd",
        "0.3.1": "60206100d160803960805160e0527ffefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe610100526100a056600436101561000d5761005e565b60046000601c376000513461006457630c55699c811861003c5760206040380360803960805160e052602060e0f35b63a56dfe4a811861005c5760206020380360803960805160e052602060e0f35b505b60006000fd5b600080fd5b6100376100a003610037610120396100376100a00360e0518161012001526101005181610140015280604001610120f3",
    }

    We can easily plug in a custom tracer by patching ethereum.evm_trace import.

    @dataclass
    class Tracer:
        code_size: int = None
        runtime_size: int = None
        init_offset: int = None
    
        def __call__(self, evm, op):
            match op:
                case Ops.CODECOPY:
                    self.init_offset = evm.stack[-2]
                    self.code_size = evm.stack[-3]
                case Ops.RETURN:
                    self.runtime_size = evm.stack[-2]
    
        @property
        def data_size(self):
            return self.runtime_size - self.code_size
    
    
    def exec_init_code(code):
        tracer = Tracer()
        interpreter.evm_trace = tracer
        interpreter.execute_code(make_deploy_message(code), prepare_env())
        return tracer
    Execute and output
    data = [
        {"version": str(version)} | asdict(exec_init_code(codes[version]))
        for version in codes
    ]
    (
        pl.DataFrame(data).with_columns(
            data_size=pl.col("runtime_size") - pl.col("code_size")
        )
    )
    shape: (9, 5)
    version code_size runtime_size init_offset data_size
    str i64 i64 i64 i64
    "0.3.10" 102 166 76 64
    "0.3.9" 103 167 72 64
    "0.3.8" 89 153 72 64
    "0.3.7" 127 191 70 64
    "0.3.6" 127 191 70 64
    "0.3.4" 125 189 70 64
    "0.3.3" 99 163 80 64
    "0.3.2" 99 163 80 64
    "0.3.1" 105 169 55 64

    These results are perfect, and we can move on to running the real init codes.

    Replay deployments

    For best results it’s easiest to replay the deployment transactions in the exact environment they have been created in. The tracer would also need and few updates to handle more complex cases like factory deployments.

    There are two ways to get opcode-resolution traces: debug_traceTransaction aka Geth-style and trace_replayTransaction in vmTrace mode aka Parity-style.

    You should choose Geth traces if you are doing the analysis on the same machine.

    Otherwise choose Parity traces paired with evm-trace for a faster drop-in replacement that sends 1000x less data over the network11. Parity format has its downsides as it’s not streamable, more complex and quite brittle12.

  • 11 Read 100x faster EVM traces with Python if you want to learn how it’s possible

  • 12 Recent examples include a random renaming of an opcode, missing push (1, 2, 3) and memory outputs.

  • Ape supports streaming request decoding, which we use to construct a trace frame iterator.

    from evm_trace.vmtrace import VMTraceFrame
    
    
    def get_geth_frames(tx: bytes) -> Iterator[VMTraceFrame]:
        frames = chain.provider._stream_request(
            "debug_traceTransaction", [encode_hex(tx)], "result.structLogs.item"
        )
        for frame in frames:
            yield VMTraceFrame(
                address=None,
                pc=frame["pc"],
                op=frame["op"],
                depth=frame["depth"],
                stack=[int(x, 16) for x in frame["stack"]],
                memory=b"".join(bytes.fromhex(x) for x in frame["memory"]),
                storage=None,
            )
    from evm_trace.vmtrace import VMTraceFrame, from_rpc_response, to_trace_frames
    
    
    def get_vmtrace_frames(tx: bytes) -> Iterator[VMTraceFrame]:
        resp = httpx.post(
            chain.provider.uri,
            json={
                "jsonrpc": "2.0",
                "id": 1,
                "method": "trace_replayTransaction",
                "params": [encode_hex(tx), ["vmTrace"]],
            },
        )
        trace = from_rpc_response(resp.content)
        return to_trace_frames(trace, copy_memory=False)

    To support factories, we need to timely grab the values from the stack at the moment each contract is initialized.

    When a contract is created, the EVM state is suspended, and we go one level deeper. There we find a fresh EVM that has an empty stack and no memory. After the init code has run, the control is returned to the suspended EVM and it’s business as usual with the exception of a newly created contract address on a stack.

    For deployments from an EOA, there is no place where the control is returned, so we can’t grab the contract address. We can only compute it as keccak(rlp.encode([deployer, nonce]))[-20:], but we don’t use it here, instead we use a placeholder name for EOA deployments and return it if we didn’t capture the requested address.

    def find_offsets(tx: bytes, address: bytes = None):
        create = 0
        current = {}
        contracts = {}
        for frame in get_vmtrace_frames(tx):
            if frame.depth == create:
                addr = frame.stack[-1].to_bytes(20, "big")
                create = 0
                contracts[addr] = current.copy()
            match frame.op:
                case "CREATE" | "CREATE2":
                    create = frame.depth
                case "CODECOPY":
                    current["init_offset"] = frame.stack[-2]
                    current["code_size"] = frame.stack[-3]
                case "RETURN":
                    current["runtime_size"] = frame.stack[-2]
        contracts["eoa"] = current.copy()
        if address:
            return contracts.get(address, contracts["eoa"])
        return contracts
    
    
    find_offsets(vypers[-2, "transaction_hash"], vypers[-2, "contract_address"])
    {'init_offset': 29, 'code_size': 829, 'runtime_size': 829}

    I benched this against all 3226 contracts we found earlier and it took 6min 11s with Geth and 7min 56s with Parity traces against Erigon on a local machine, with 4x more CPU time with Parity.

    A third method

    But what if I told you we can make it 50x faster? One downside though, we’ll need to write Javascript.

    You probably know that debug_traceTransaction has a tracer argument. Common useful tracers13 include callTracer and prestateTracer.

    Instead of a standard tracer name, you can pass Javascript14 code as the tracer argument. Let’s see what happens if we do that.

    {
        create: 0,
        current: {},
        contracts: [],
        step: function(log, db) {
            if (log.getDepth() == this.create) {
                const addr = log.stack.peek(0)
                this.contracts.push(Object.assign({addr: addr}, this.current))
                this.create = 0
            }
            if (log.op == 'CREATE' || log.op == 'CREATE2') {
                this.create = log.getDepth()
            }
            if (log.op == 'CODECOPY') {
                this.current.init_offset = log.stack.peek(1)
                this.current.code_size = log.stack.peek(2)
            }
            if (log.op == 'RETURN') {
                this.current.runtime_size = log.stack.peek(1)
            }
        },
        fault: function(log, db) {this.contracts.push({error: JSON.stringify(log)})},
        result: function(ctx, db) {
            this.contracts.push(Object.assign({addr: null}, this.current))
            return this.contracts
        }
    }

    I’m not friends with Javascript, so excuse some post-processing to arrive at the same format.

    def trace_custom(tx: bytes, address: bytes):
        resp = chain.provider._make_request(
            "debug_traceTransaction", [encode_hex(tx), {"tracer": tracer}]
        )
        results = {}
        for item in resp:
            if item["addr"] is not None:
                item["addr"] = int(item["addr"]).to_bytes(20, "big")
    
            results[item["addr"]] = {
                "runtime_size": int(item["runtime_size"]),
                "init_offset": int(item["init_offset"]) if "init_offset" in item else None,
                "code_size": int(item["code_size"]) if "code_size" in item else None,
            }
    
        if address is not None:
            return results.get(address, results[None])
    
        return results
    
    
    trace_custom(vypers[-2, "transaction_hash"], vypers[-2, "contract_address"])
    {'runtime_size': 829, 'init_offset': 29, 'code_size': 829}

    As you can see, we got the same results. And with the new tracer it only takes 7 seconds to check every contract deployment that interests us.

    Cleanup code

    After acquiring the metadata, we can proceed with deleting it.

    def clean_code(code, code_size):
        # 0.3.1 strip immutables
        code = code[:code_size]
        # 0.3.5+ strip vyper signature size
        if code[-2:] == b"\x00\x0b":
            code = code[:-13]
        # 0.3.4 strip vyper signtaure
        elif code[-11:-3] == b"\xa1\x65vyper\x83":
            code = code[:-11]
    
        return code
    
    
    vypers = vypers.with_columns(
        clean_code=pl.struct("code", "code_size").apply(
            lambda d: clean_code(d["code"], d["code_size"])
        )
    )

    Find vulnerable contracts

    The disclosure mentions uint256_addmod, uint256_mulmod, ecadd and ecmul as the affected functions. The first two are opcodes, while the other two are precompiles.

    Disassemble

    In both cases we’ll need to disassemble the code, a cakewalk compared to what we have endured. We read the code sequentially, look up the opcodes, and when we encounter PUSH1-PUSH32, we read the value and skip ahead.

    def disasm(code):
        result = []
        pc = 0
        while pc < len(code):
            op = code[pc]
            opcode = opcodes.get(op, f"unknown_{hex(op)}")
            result.append(opcode)
            if Ops.PUSH1.value <= op <= Ops.PUSH32.value:
                push_size = op - Ops.PUSH0.value
                push_value = code[pc + 1 : pc + 1 + push_size]
                result.append(hex(int.from_bytes(push_value, "big")))
                pc += push_size
            pc += 1
    
        return " ".join(result)
    
    
    disasm(vypers[-1, "clean_code"])
    'PUSH1 0x3 CALLDATASIZE GT PUSH2 0xc JUMPI PUSH2 0x1882 JUMP JUMPDEST PUSH0 CALLDATALOAD PUSH1 0xe0 SHR CALLVALUE PUSH2 0x240a JUMPI PUSH4 0xfc0c546a DUP2 XOR PUSH2 0x2d JUMPI PUSH1 0x1 SLOAD PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x40 RETURN JUMPDEST PUSH4 0x47fc9aa DUP2 XOR PUSH2 0x44 JUMPI PUSH1 0x2 SLOAD PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x40 RETURN JUMPDEST PUSH4 0xcbf9fe5f DUP2 XOR PUSH2 0x87 JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH1 0x40 MSTORE PUSH1 0x3 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK DUP1 SLOAD PUSH1 0x60 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH1 0x80 MSTORE POP PUSH1 0x40 PUSH1 0x60 RETURN JUMPDEST PUSH4 0x900cf0cf DUP2 XOR PUSH2 0x9e JUMPI PUSH1 0x4 SLOAD PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x40 RETURN JUMPDEST PUSH4 0xd1febfb9 DUP2 XOR PUSH2 0xf2 JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD PUSH13 0x1431e0fae6d7217ca9fffffff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL PUSH1 0x5 ADD DUP1 SLOAD PUSH1 0x40 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH1 0x60 MSTORE PUSH1 0x2 DUP2 ADD SLOAD PUSH1 0x80 MSTORE PUSH1 0x3 DUP2 ADD SLOAD PUSH1 0xa0 MSTORE POP PUSH1 0x80 PUSH1 0x40 RETURN JUMPDEST PUSH4 0x28d09d47 DUP2 XOR PUSH2 0x166 JUMPI PUSH1 0x44 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH1 0x40 MSTORE PUSH13 0x50c783eb9b5c85f2a80000005 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK PUSH1 0x24 CALLDATALOAD PUSH4 0x3b9ac9ff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL DUP2 ADD SWAP1 POP DUP1 SLOAD PUSH1 0x60 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH1 0x80 MSTORE PUSH1 0x2 DUP2 ADD SLOAD PUSH1 0xa0 MSTORE PUSH1 0x3 DUP2 ADD SLOAD PUSH1 0xc0 MSTORE POP PUSH1 0x80 PUSH1 0x60 RETURN JUMPDEST PUSH4 0x10ae757 DUP2 XOR PUSH2 0x1ab JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH1 0x40 MSTORE PUSH13 0x50c783eb9b5c85f2a80000006 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SLOAD PUSH1 0x60 MSTORE PUSH1 0x20 PUSH1 0x60 RETURN JUMPDEST PUSH4 0x71197484 DUP2 XOR PUSH2 0x1e2 JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH13 0x50c783eb9b5c85f2a80000007 PUSH1 0x4 CALLDATALOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SLOAD PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x40 RETURN JUMPDEST PUSH4 0xf77c4791 DUP2 XOR PUSH2 0x205 JUMPI PUSH13 0x50c783eb9b5c85f2a80000008 SLOAD PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x40 RETURN JUMPDEST PUSH4 0xbef97c87 DUP2 XOR PUSH2 0x228 JUMPI PUSH13 0x50c783eb9b5c85f2a80000009 SLOAD PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x40 RETURN JUMPDEST PUSH4 0x6fdde03 DUP2 XOR PUSH2 0x2bb JUMPI PUSH1 0x20 DUP1 PUSH1 0x40 MSTORE DUP1 PUSH1 0x40 ADD PUSH13 0x50c783eb9b5c85f2a8000000a SLOAD PUSH1 0x20 DUP3 ADD PUSH0 DUP3 PUSH1 0x1f ADD PUSH1 0x5 SHR PUSH1 0x2 DUP2 GT PUSH2 0x240a JUMPI DUP1 ISZERO PUSH2 0x28b JUMPI SWAP1 JUMPDEST DUP1 PUSH13 0x50c783eb9b5c85f2a8000000b ADD SLOAD DUP2 PUSH1 0x5 SHL DUP5 ADD MSTORE PUSH1 0x1 ADD DUP2 DUP2 XOR PUSH2 0x268 JUMPI JUMPDEST POP POP POP DUP1 DUP3 MSTORE POP DUP1 MLOAD DUP1 PUSH1 0x20 DUP4 ADD ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH1 0x1f NOT PUSH1 0x1f DUP3 MLOAD PUSH1 0x20 ADD ADD AND SWAP1 POP DUP2 ADD SWAP1 POP PUSH1 0x40 RETURN JUMPDEST PUSH4 0x95d89b41 DUP2 XOR PUSH2 0x322 JUMPI PUSH1 0x20 DUP1 PUSH1 0x40 MSTORE DUP1 PUSH1 0x40 ADD PUSH13 0x50c783eb9b5c85f2a8000000d SLOAD PUSH1 0x20 DUP3 ADD PUSH13 0x50c783eb9b5c85f2a8000000e SLOAD DUP2 MSTORE POP DUP1 DUP3 MSTORE POP DUP1 MLOAD DUP1 PUSH1 0x20 DUP4 ADD ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH1 0x1f NOT PUSH1 0x1f DUP3 MLOAD PUSH1 0x20 ADD ADD AND SWAP1 POP DUP2 ADD SWAP1 POP PUSH1 0x40 RETURN JUMPDEST PUSH4 0x54fd4d50 DUP2 XOR PUSH2 0x389 JUMPI PUSH1 0x20 DUP1 PUSH1 0x40 MSTORE DUP1 PUSH1 0x40 ADD PUSH13 0x50c783eb9b5c85f2a8000000f SLOAD PUSH1 0x20 DUP3 ADD PUSH13 0x50c783eb9b5c85f2a80000010 SLOAD DUP2 MSTORE POP DUP1 DUP3 MSTORE POP DUP1 MLOAD DUP1 PUSH1 0x20 DUP4 ADD ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH1 0x1f NOT PUSH1 0x1f DUP3 MLOAD PUSH1 0x20 ADD ADD AND SWAP1 POP DUP2 ADD SWAP1 POP PUSH1 0x40 RETURN JUMPDEST PUSH4 0x313ce567 DUP2 XOR PUSH2 0x3ac JUMPI PUSH13 0x50c783eb9b5c85f2a80000011 SLOAD PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x40 RETURN JUMPDEST PUSH4 0x8ff36fd1 DUP2 XOR PUSH2 0x3cf JUMPI PUSH13 0x50c783eb9b5c85f2a80000012 SLOAD PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x40 RETURN JUMPDEST PUSH4 0x7175d4f7 DUP2 XOR PUSH2 0x3f2 JUMPI PUSH13 0x50c783eb9b5c85f2a80000013 SLOAD PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x40 RETURN JUMPDEST PUSH4 0xf851a440 DUP2 XOR PUSH2 0x415 JUMPI PUSH13 0x50c783eb9b5c85f2a80000014 SLOAD PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x40 RETURN JUMPDEST PUSH4 0x17f7182a DUP2 XOR PUSH2 0x438 JUMPI PUSH13 0x50c783eb9b5c85f2a80000015 SLOAD PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x40 RETURN JUMPDEST PUSH4 0x6b441a40 DUP2 XOR PUSH2 0x4ae JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH1 0x40 MSTORE PUSH13 0x50c783eb9b5c85f2a80000014 SLOAD CALLER XOR PUSH2 0x240a JUMPI PUSH1 0x40 MLOAD PUSH13 0x50c783eb9b5c85f2a80000015 SSTORE PUSH32 0x2f56810a6bf40af059b96d3aea4db54081f378029a518390491093a7b67032e9 PUSH1 0x40 MLOAD PUSH1 0x60 MSTORE PUSH1 0x20 PUSH1 0x60 LOG1 STOP JUMPDEST PUSH4 0x6a1c05ae DUP2 XOR PUSH2 0x528 JUMPI PUSH13 0x50c783eb9b5c85f2a80000014 SLOAD CALLER XOR PUSH2 0x240a JUMPI PUSH13 0x50c783eb9b5c85f2a80000015 SLOAD PUSH1 0x40 MSTORE PUSH1 0x40 MLOAD ISZERO PUSH2 0x240a JUMPI PUSH1 0x40 MLOAD PUSH13 0x50c783eb9b5c85f2a80000014 SSTORE PUSH32 0xebee2d5739011062cb4f14113f3b36bf0ffe3da5c0568f64189d1012a1189105 PUSH1 0x40 MLOAD PUSH1 0x60 MSTORE PUSH1 0x20 PUSH1 0x60 LOG1 STOP JUMPDEST PUSH4 0x57f901e2 DUP2 XOR PUSH2 0x572 JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH1 0x40 MSTORE PUSH13 0x50c783eb9b5c85f2a80000014 SLOAD CALLER XOR PUSH2 0x240a JUMPI PUSH1 0x40 MLOAD PUSH13 0x50c783eb9b5c85f2a80000012 SSTORE STOP JUMPDEST PUSH4 0x8e5b490f DUP2 XOR PUSH2 0x5b2 JUMPI PUSH13 0x50c783eb9b5c85f2a80000014 SLOAD CALLER XOR PUSH2 0x240a JUMPI PUSH13 0x50c783eb9b5c85f2a80000012 SLOAD PUSH13 0x50c783eb9b5c85f2a80000013 SSTORE STOP JUMPDEST PUSH4 0x7c74a174 DUP2 XOR PUSH2 0x630 JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH1 0x40 MSTORE PUSH13 0x50c783eb9b5c85f2a80000006 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SLOAD PUSH1 0x60 MSTORE PUSH13 0x50c783eb9b5c85f2a80000005 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK PUSH1 0x60 MLOAD PUSH4 0x3b9ac9ff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL DUP2 ADD SWAP1 POP PUSH1 0x1 DUP2 ADD SWAP1 POP SLOAD PUSH1 0x80 MSTORE PUSH1 0x20 PUSH1 0x80 RETURN JUMPDEST PUSH4 0xda020a18 DUP2 XOR PUSH2 0x690 JUMPI PUSH1 0x44 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH1 0x40 MSTORE PUSH13 0x50c783eb9b5c85f2a80000005 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK PUSH1 0x24 CALLDATALOAD PUSH4 0x3b9ac9ff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL DUP2 ADD SWAP1 POP PUSH1 0x2 DUP2 ADD SWAP1 POP SLOAD PUSH1 0x60 MSTORE PUSH1 0x20 PUSH1 0x60 RETURN JUMPDEST PUSH4 0xadc63589 DUP2 XOR PUSH2 0x6cf JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH1 0x40 MSTORE PUSH1 0x3 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK PUSH1 0x1 DUP2 ADD SWAP1 POP SLOAD PUSH1 0x60 MSTORE PUSH1 0x20 PUSH1 0x60 RETURN JUMPDEST PUSH4 0xc2c4c5c1 DUP2 XOR PUSH2 0x6ea JUMPI PUSH1 0xa0 CALLDATASIZE PUSH1 0x40 CALLDATACOPY PUSH2 0x6e8 PUSH2 0x1979 JUMP JUMPDEST STOP JUMPDEST PUSH4 0x3a46273e DUP2 XOR PUSH2 0x88b JUMPI PUSH1 0x44 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH2 0x5e0 MSTORE PUSH0 SLOAD PUSH1 0x2 EQ PUSH2 0x240a JUMPI PUSH1 0x2 PUSH0 SSTORE PUSH1 0x3 PUSH2 0x5e0 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK DUP1 SLOAD PUSH2 0x600 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x620 MSTORE POP PUSH1 0x24 CALLDATALOAD ISZERO PUSH2 0x240a JUMPI PUSH1 0x1 PUSH2 0x600 MLOAD SLT ISZERO PUSH2 0x7b1 JUMPI PUSH1 0x16 PUSH2 0x640 MSTORE PUSH32 0x4e6f206578697374696e67206c6f636b20666f756e6400000000000000000000 PUSH2 0x660 MSTORE PUSH2 0x640 POP PUSH2 0x640 MLOAD DUP1 PUSH2 0x660 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x600 MSTORE PUSH1 0x20 PUSH2 0x620 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x640 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x61c REVERT JUMPDEST TIMESTAMP PUSH2 0x620 MLOAD GT PUSH2 0x845 JUMPI PUSH1 0x24 PUSH2 0x640 MSTORE PUSH32 0x43616e6e6f742061646420746f2065787069726564206c6f636b2e2057697468 PUSH2 0x660 MSTORE PUSH32 0x6472617700000000000000000000000000000000000000000000000000000000 PUSH2 0x680 MSTORE PUSH2 0x640 POP PUSH2 0x640 MLOAD DUP1 PUSH2 0x660 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x600 MSTORE PUSH1 0x20 PUSH2 0x620 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x640 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x61c REVERT JUMPDEST PUSH2 0x5e0 MLOAD PUSH2 0x3e0 MSTORE PUSH1 0x24 CALLDATALOAD PUSH2 0x400 MSTORE PUSH0 PUSH2 0x420 MSTORE PUSH1 0x3 PUSH2 0x5e0 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK DUP1 SLOAD PUSH2 0x440 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x460 MSTORE POP PUSH0 PUSH2 0x480 MSTORE PUSH2 0x885 PUSH2 0x203c JUMP JUMPDEST PUSH1 0x3 PUSH0 SSTORE STOP JUMPDEST PUSH4 0x65fc3873 DUP2 XOR PUSH2 0xab8 JUMPI PUSH1 0x44 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH0 SLOAD PUSH1 0x2 EQ PUSH2 0x240a JUMPI PUSH1 0x2 PUSH0 SSTORE CALLER PUSH1 0x40 MSTORE PUSH2 0x8b7 PUSH2 0x1886 JUMP JUMPDEST PUSH1 0x24 CALLDATALOAD PUSH3 0x93a80 DUP2 DIV SWAP1 POP PUSH3 0x93a80 DUP2 MUL DUP2 PUSH3 0x93a80 DUP3 DIV XOR PUSH2 0x240a JUMPI SWAP1 POP PUSH2 0x5e0 MSTORE PUSH1 0x3 CALLER PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK DUP1 SLOAD PUSH2 0x600 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x620 MSTORE POP PUSH1 0x4 CALLDATALOAD ISZERO PUSH2 0x240a JUMPI PUSH2 0x600 MLOAD ISZERO PUSH2 0x96c JUMPI PUSH1 0x19 PUSH2 0x640 MSTORE PUSH32 0x5769746864726177206f6c6420746f6b656e7320666972737400000000000000 PUSH2 0x660 MSTORE PUSH2 0x640 POP PUSH2 0x640 MLOAD DUP1 PUSH2 0x660 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x600 MSTORE PUSH1 0x20 PUSH2 0x620 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x640 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x61c REVERT JUMPDEST TIMESTAMP PUSH2 0x5e0 MLOAD GT PUSH2 0xa00 JUMPI PUSH1 0x26 PUSH2 0x640 MSTORE PUSH32 0x43616e206f6e6c79206c6f636b20756e74696c2074696d6520696e2074686520 PUSH2 0x660 MSTORE PUSH32 0x6675747572650000000000000000000000000000000000000000000000000000 PUSH2 0x680 MSTORE PUSH2 0x640 POP PUSH2 0x640 MLOAD DUP1 PUSH2 0x660 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x600 MSTORE PUSH1 0x20 PUSH2 0x620 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x640 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x61c REVERT JUMPDEST TIMESTAMP PUSH4 0x784ce00 DUP2 ADD DUP2 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP PUSH2 0x5e0 MLOAD GT ISZERO PUSH2 0xa80 JUMPI PUSH1 0x1e PUSH2 0x640 MSTORE PUSH32 0x566f74696e67206c6f636b2063616e2062652034207965617273206d61780000 PUSH2 0x660 MSTORE PUSH2 0x640 POP PUSH2 0x640 MLOAD DUP1 PUSH2 0x660 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x600 MSTORE PUSH1 0x20 PUSH2 0x620 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x640 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x61c REVERT JUMPDEST CALLER PUSH2 0x3e0 MSTORE PUSH1 0x4 CALLDATALOAD PUSH2 0x400 MSTORE PUSH2 0x5e0 MLOAD PUSH2 0x420 MSTORE PUSH2 0x600 MLOAD PUSH2 0x440 MSTORE PUSH2 0x620 MLOAD PUSH2 0x460 MSTORE PUSH1 0x1 PUSH2 0x480 MSTORE PUSH2 0xab2 PUSH2 0x203c JUMP JUMPDEST PUSH1 0x3 PUSH0 SSTORE STOP JUMPDEST PUSH4 0x4957677c DUP2 XOR PUSH2 0xc42 JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH0 SLOAD PUSH1 0x2 EQ PUSH2 0x240a JUMPI PUSH1 0x2 PUSH0 SSTORE CALLER PUSH1 0x40 MSTORE PUSH2 0xae4 PUSH2 0x1886 JUMP JUMPDEST PUSH1 0x3 CALLER PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK DUP1 SLOAD PUSH2 0x5e0 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x600 MSTORE POP PUSH1 0x4 CALLDATALOAD ISZERO PUSH2 0x240a JUMPI PUSH1 0x1 PUSH2 0x5e0 MLOAD SLT ISZERO PUSH2 0xb79 JUMPI PUSH1 0x16 PUSH2 0x620 MSTORE PUSH32 0x4e6f206578697374696e67206c6f636b20666f756e6400000000000000000000 PUSH2 0x640 MSTORE PUSH2 0x620 POP PUSH2 0x620 MLOAD DUP1 PUSH2 0x640 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x5e0 MSTORE PUSH1 0x20 PUSH2 0x600 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x620 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x5fc REVERT JUMPDEST TIMESTAMP PUSH2 0x600 MLOAD GT PUSH2 0xc0d JUMPI PUSH1 0x24 PUSH2 0x620 MSTORE PUSH32 0x43616e6e6f742061646420746f2065787069726564206c6f636b2e2057697468 PUSH2 0x640 MSTORE PUSH32 0x6472617700000000000000000000000000000000000000000000000000000000 PUSH2 0x660 MSTORE PUSH2 0x620 POP PUSH2 0x620 MLOAD DUP1 PUSH2 0x640 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x5e0 MSTORE PUSH1 0x20 PUSH2 0x600 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x620 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x5fc REVERT JUMPDEST CALLER PUSH2 0x3e0 MSTORE PUSH1 0x4 CALLDATALOAD PUSH2 0x400 MSTORE PUSH0 PUSH2 0x420 MSTORE PUSH2 0x5e0 MLOAD PUSH2 0x440 MSTORE PUSH2 0x600 MLOAD PUSH2 0x460 MSTORE PUSH1 0x2 PUSH2 0x480 MSTORE PUSH2 0xc3c PUSH2 0x203c JUMP JUMPDEST PUSH1 0x3 PUSH0 SSTORE STOP JUMPDEST PUSH4 0xeff7a612 DUP2 XOR PUSH2 0xeb5 JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH0 SLOAD PUSH1 0x2 EQ PUSH2 0x240a JUMPI PUSH1 0x2 PUSH0 SSTORE CALLER PUSH1 0x40 MSTORE PUSH2 0xc6e PUSH2 0x1886 JUMP JUMPDEST PUSH1 0x3 CALLER PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK DUP1 SLOAD PUSH2 0x5e0 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x600 MSTORE POP PUSH1 0x4 CALLDATALOAD PUSH3 0x93a80 DUP2 DIV SWAP1 POP PUSH3 0x93a80 DUP2 MUL DUP2 PUSH3 0x93a80 DUP3 DIV XOR PUSH2 0x240a JUMPI SWAP1 POP PUSH2 0x620 MSTORE TIMESTAMP PUSH2 0x600 MLOAD GT PUSH2 0xd1c JUMPI PUSH1 0xc PUSH2 0x640 MSTORE PUSH32 0x4c6f636b20657870697265640000000000000000000000000000000000000000 PUSH2 0x660 MSTORE PUSH2 0x640 POP PUSH2 0x640 MLOAD DUP1 PUSH2 0x660 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x600 MSTORE PUSH1 0x20 PUSH2 0x620 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x640 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x61c REVERT JUMPDEST PUSH1 0x1 PUSH2 0x5e0 MLOAD SLT ISZERO PUSH2 0xd8d JUMPI PUSH1 0x11 PUSH2 0x640 MSTORE PUSH32 0x4e6f7468696e67206973206c6f636b6564000000000000000000000000000000 PUSH2 0x660 MSTORE PUSH2 0x640 POP PUSH2 0x640 MLOAD DUP1 PUSH2 0x660 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x600 MSTORE PUSH1 0x20 PUSH2 0x620 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x640 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x61c REVERT JUMPDEST PUSH2 0x600 MLOAD PUSH2 0x620 MLOAD GT PUSH2 0xdff JUMPI PUSH1 0x1f PUSH2 0x640 MSTORE PUSH32 0x43616e206f6e6c7920696e637265617365206c6f636b206475726174696f6e00 PUSH2 0x660 MSTORE PUSH2 0x640 POP PUSH2 0x640 MLOAD DUP1 PUSH2 0x660 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x600 MSTORE PUSH1 0x20 PUSH2 0x620 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x640 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x61c REVERT JUMPDEST TIMESTAMP PUSH4 0x784ce00 DUP2 ADD DUP2 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP PUSH2 0x620 MLOAD GT ISZERO PUSH2 0xe7f JUMPI PUSH1 0x1e PUSH2 0x640 MSTORE PUSH32 0x566f74696e67206c6f636b2063616e2062652034207965617273206d61780000 PUSH2 0x660 MSTORE PUSH2 0x640 POP PUSH2 0x640 MLOAD DUP1 PUSH2 0x660 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x600 MSTORE PUSH1 0x20 PUSH2 0x620 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x640 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x61c REVERT JUMPDEST CALLER PUSH2 0x3e0 MSTORE PUSH0 PUSH2 0x400 MSTORE PUSH2 0x620 MLOAD PUSH2 0x420 MSTORE PUSH2 0x5e0 MLOAD PUSH2 0x440 MSTORE PUSH2 0x600 MLOAD PUSH2 0x460 MSTORE PUSH1 0x3 PUSH2 0x480 MSTORE PUSH2 0xeaf PUSH2 0x203c JUMP JUMPDEST PUSH1 0x3 PUSH0 SSTORE STOP JUMPDEST PUSH4 0x3ccfd60b DUP2 XOR PUSH2 0x10c0 JUMPI PUSH0 SLOAD PUSH1 0x2 EQ PUSH2 0x240a JUMPI PUSH1 0x2 PUSH0 SSTORE PUSH1 0x3 CALLER PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK DUP1 SLOAD PUSH2 0x3e0 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x400 MSTORE POP PUSH2 0x400 MLOAD TIMESTAMP LT ISZERO PUSH2 0xf59 JUMPI PUSH1 0x16 PUSH2 0x420 MSTORE PUSH32 0x546865206c6f636b206469646e27742065787069726500000000000000000000 PUSH2 0x440 MSTORE PUSH2 0x420 POP PUSH2 0x420 MLOAD DUP1 PUSH2 0x440 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH2 0x3e0 MSTORE PUSH1 0x20 PUSH2 0x400 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH2 0x420 MLOAD ADD AND PUSH1 0x44 ADD PUSH2 0x3fc REVERT JUMPDEST PUSH2 0x3e0 MLOAD PUSH0 DUP2 SLT PUSH2 0x240a JUMPI PUSH2 0x420 MSTORE PUSH2 0x3e0 MLOAD PUSH2 0x440 MSTORE PUSH2 0x400 MLOAD PUSH2 0x460 MSTORE PUSH0 PUSH2 0x400 MSTORE PUSH0 PUSH2 0x3e0 MSTORE PUSH1 0x3 CALLER PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK PUSH2 0x3e0 MLOAD DUP2 SSTORE PUSH2 0x400 MLOAD PUSH1 0x1 DUP3 ADD SSTORE POP PUSH1 0x2 SLOAD PUSH2 0x480 MSTORE PUSH2 0x480 MLOAD PUSH2 0x420 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH1 0x2 SSTORE CALLER PUSH1 0x40 MSTORE PUSH2 0x440 MLOAD PUSH1 0x60 MSTORE PUSH2 0x460 MLOAD PUSH1 0x80 MSTORE PUSH2 0x3e0 MLOAD PUSH1 0xa0 MSTORE PUSH2 0x400 MLOAD PUSH1 0xc0 MSTORE PUSH2 0xfe6 PUSH2 0x1979 JUMP JUMPDEST PUSH1 0x1 SLOAD PUSH4 0xa9059cbb PUSH2 0x4a0 MSTORE CALLER PUSH2 0x4c0 MSTORE PUSH2 0x420 MLOAD PUSH2 0x4e0 MSTORE PUSH1 0x20 PUSH2 0x4a0 PUSH1 0x44 PUSH2 0x4bc PUSH0 DUP6 GAS CALL PUSH2 0x1019 JUMPI RETURNDATASIZE PUSH0 PUSH0 RETURNDATACOPY RETURNDATASIZE PUSH0 REVERT JUMPDEST PUSH1 0x20 RETURNDATASIZE LT PUSH2 0x240a JUMPI PUSH2 0x4a0 MLOAD DUP1 PUSH1 0x1 SHR PUSH2 0x240a JUMPI PUSH2 0x500 MSTORE PUSH2 0x500 SWAP1 POP MLOAD ISZERO PUSH2 0x240a JUMPI CALLER PUSH32 0xf279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568 PUSH2 0x420 MLOAD PUSH2 0x4a0 MSTORE TIMESTAMP PUSH2 0x4c0 MSTORE PUSH1 0x40 PUSH2 0x4a0 LOG2 PUSH32 0x5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c PUSH2 0x480 MLOAD PUSH2 0x4a0 MSTORE PUSH2 0x480 MLOAD PUSH2 0x420 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x4c0 MSTORE PUSH1 0x40 PUSH2 0x4a0 LOG1 PUSH1 0x3 PUSH0 SSTORE STOP JUMPDEST PUSH4 0x70a08231 DUP2 XOR PUSH2 0x10dc JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI TIMESTAMP PUSH1 0x60 MSTORE PUSH2 0x10f5 JUMP JUMPDEST PUSH3 0xfdd58e DUP2 XOR PUSH2 0x120e JUMPI PUSH1 0x44 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x24 CALLDATALOAD PUSH1 0x60 MSTORE JUMPDEST PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH1 0x40 MSTORE PUSH13 0x50c783eb9b5c85f2a80000006 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SLOAD PUSH1 0x80 MSTORE PUSH1 0x80 MLOAD PUSH2 0x1135 JUMPI PUSH0 PUSH1 0xa0 MSTORE PUSH1 0x20 PUSH1 0xa0 PUSH2 0x120c JUMP JUMPDEST PUSH13 0x50c783eb9b5c85f2a80000005 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK PUSH1 0x80 MLOAD PUSH4 0x3b9ac9ff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL DUP2 ADD SWAP1 POP DUP1 SLOAD PUSH1 0xa0 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH1 0xc0 MSTORE PUSH1 0x2 DUP2 ADD SLOAD PUSH1 0xe0 MSTORE PUSH1 0x3 DUP2 ADD SLOAD PUSH2 0x100 MSTORE POP PUSH1 0xa0 MLOAD PUSH1 0xc0 MLOAD PUSH1 0x60 MLOAD PUSH1 0xe0 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 PUSH1 0x7f SHR PUSH2 0x240a JUMPI DUP1 DUP3 MUL DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 DUP3 SUB DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH1 0xa0 MSTORE PUSH32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff PUSH1 0xa0 MLOAD SGT PUSH2 0x11f8 JUMPI PUSH0 PUSH1 0xa0 MSTORE JUMPDEST PUSH1 0xa0 MLOAD PUSH0 DUP2 SLT PUSH2 0x240a JUMPI PUSH2 0x120 MSTORE PUSH1 0x20 PUSH2 0x120 JUMPDEST RETURN JUMPDEST PUSH4 0x4ee2cd7e DUP2 XOR PUSH2 0x157e JUMPI PUSH1 0x44 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH2 0x100 MSTORE NUMBER PUSH1 0x24 CALLDATALOAD GT PUSH2 0x240a JUMPI PUSH0 PUSH2 0x120 MSTORE PUSH13 0x50c783eb9b5c85f2a80000006 PUSH2 0x100 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SLOAD PUSH2 0x140 MSTORE PUSH0 PUSH1 0x80 SWAP1 JUMPDEST DUP1 PUSH2 0x160 MSTORE PUSH2 0x140 MLOAD PUSH2 0x120 MLOAD LT PUSH2 0x127a JUMPI PUSH2 0x1316 JUMP JUMPDEST PUSH2 0x120 MLOAD PUSH2 0x140 MLOAD DUP1 DUP3 ADD DUP3 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH1 0x1 DUP2 ADD DUP2 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP DUP1 PUSH1 0x1 SHR SWAP1 POP PUSH2 0x180 MSTORE PUSH1 0x24 CALLDATALOAD PUSH13 0x50c783eb9b5c85f2a80000005 PUSH2 0x100 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK PUSH2 0x180 MLOAD PUSH4 0x3b9ac9ff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL DUP2 ADD SWAP1 POP PUSH1 0x3 DUP2 ADD SWAP1 POP SLOAD GT ISZERO PUSH2 0x1302 JUMPI PUSH2 0x180 MLOAD PUSH1 0x1 DUP2 SUB DUP2 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP PUSH2 0x140 MSTORE PUSH2 0x130b JUMP JUMPDEST PUSH2 0x180 MLOAD PUSH2 0x120 MSTORE JUMPDEST PUSH1 0x1 ADD DUP2 DUP2 XOR PUSH2 0x1263 JUMPI JUMPDEST POP POP PUSH13 0x50c783eb9b5c85f2a80000005 PUSH2 0x100 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK PUSH2 0x120 MLOAD PUSH4 0x3b9ac9ff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL DUP2 ADD SWAP1 POP DUP1 SLOAD PUSH2 0x160 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x180 MSTORE PUSH1 0x2 DUP2 ADD SLOAD PUSH2 0x1a0 MSTORE PUSH1 0x3 DUP2 ADD SLOAD PUSH2 0x1c0 MSTORE POP PUSH1 0x4 SLOAD PUSH2 0x1e0 MSTORE PUSH1 0x24 CALLDATALOAD PUSH1 0x40 MSTORE PUSH2 0x1e0 MLOAD PUSH1 0x60 MSTORE PUSH2 0x138a PUSH2 0x220 PUSH2 0x21f4 JUMP JUMPDEST PUSH2 0x220 MLOAD PUSH2 0x200 MSTORE PUSH2 0x200 MLOAD PUSH13 0x1431e0fae6d7217ca9fffffff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL PUSH1 0x5 ADD DUP1 SLOAD PUSH2 0x220 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x240 MSTORE PUSH1 0x2 DUP2 ADD SLOAD PUSH2 0x260 MSTORE PUSH1 0x3 DUP2 ADD SLOAD PUSH2 0x280 MSTORE POP PUSH1 0x40 CALLDATASIZE PUSH2 0x2a0 CALLDATACOPY PUSH2 0x1e0 MLOAD PUSH2 0x200 MLOAD LT PUSH2 0x1419 JUMPI NUMBER PUSH2 0x280 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x2a0 MSTORE TIMESTAMP PUSH2 0x260 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x2c0 MSTORE PUSH2 0x149b JUMP JUMPDEST PUSH2 0x200 MLOAD PUSH1 0x1 DUP2 ADD DUP2 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP PUSH13 0x1431e0fae6d7217ca9fffffff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL PUSH1 0x5 ADD DUP1 SLOAD PUSH2 0x2e0 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x300 MSTORE PUSH1 0x2 DUP2 ADD SLOAD PUSH2 0x320 MSTORE PUSH1 0x3 DUP2 ADD SLOAD PUSH2 0x340 MSTORE POP PUSH2 0x340 MLOAD PUSH2 0x280 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x2a0 MSTORE PUSH2 0x320 MLOAD PUSH2 0x260 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x2c0 MSTORE JUMPDEST PUSH2 0x260 MLOAD PUSH2 0x2e0 MSTORE PUSH2 0x2a0 MLOAD ISZERO PUSH2 0x1501 JUMPI PUSH2 0x2e0 MLOAD PUSH2 0x2c0 MLOAD PUSH1 0x24 CALLDATALOAD PUSH2 0x280 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 DUP3 MUL DUP2 ISZERO DUP4 DUP4 DUP4 DIV EQ OR ISZERO PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x2a0 MLOAD DUP1 ISZERO PUSH2 0x240a JUMPI DUP1 DUP3 DIV SWAP1 POP SWAP1 POP DUP1 DUP3 ADD DUP3 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x2e0 MSTORE JUMPDEST PUSH2 0x160 MLOAD PUSH2 0x180 MLOAD PUSH2 0x2e0 MLOAD PUSH2 0x1a0 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 PUSH1 0x7f SHR PUSH2 0x240a JUMPI DUP1 DUP3 MUL DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 DUP3 SUB DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x160 MSTORE PUSH0 PUSH2 0x160 MLOAD SLT ISZERO PUSH2 0x1567 JUMPI PUSH0 PUSH2 0x300 MSTORE PUSH1 0x20 PUSH2 0x300 PUSH2 0x157c JUMP JUMPDEST PUSH2 0x160 MLOAD PUSH0 DUP2 SLT PUSH2 0x240a JUMPI PUSH2 0x300 MSTORE PUSH1 0x20 PUSH2 0x300 JUMPDEST RETURN JUMPDEST PUSH4 0x18160ddd DUP2 XOR PUSH2 0x1593 JUMPI TIMESTAMP PUSH2 0x1c0 MSTORE PUSH2 0x15ae JUMP JUMPDEST PUSH4 0xbd85b039 DUP2 XOR PUSH2 0x162a JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD PUSH2 0x1c0 MSTORE JUMPDEST PUSH1 0x4 SLOAD PUSH2 0x1e0 MSTORE PUSH2 0x1e0 MLOAD PUSH13 0x1431e0fae6d7217ca9fffffff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL PUSH1 0x5 ADD DUP1 SLOAD PUSH2 0x200 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x220 MSTORE PUSH1 0x2 DUP2 ADD SLOAD PUSH2 0x240 MSTORE PUSH1 0x3 DUP2 ADD SLOAD PUSH2 0x260 MSTORE POP PUSH1 0x20 PUSH2 0x200 MLOAD PUSH1 0x40 MSTORE PUSH2 0x220 MLOAD PUSH1 0x60 MSTORE PUSH2 0x240 MLOAD PUSH1 0x80 MSTORE PUSH2 0x260 MLOAD PUSH1 0xa0 MSTORE PUSH2 0x1c0 MLOAD PUSH1 0xc0 MSTORE PUSH2 0x1625 PUSH2 0x280 PUSH2 0x22a2 JUMP JUMPDEST PUSH2 0x280 RETURN JUMPDEST PUSH4 0x981b24d0 DUP2 XOR PUSH2 0x1836 JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI NUMBER PUSH1 0x4 CALLDATALOAD GT PUSH2 0x240a JUMPI PUSH1 0x4 SLOAD PUSH2 0x1c0 MSTORE PUSH1 0x4 CALLDATALOAD PUSH1 0x40 MSTORE PUSH2 0x1c0 MLOAD PUSH1 0x60 MSTORE PUSH2 0x1665 PUSH2 0x200 PUSH2 0x21f4 JUMP JUMPDEST PUSH2 0x200 MLOAD PUSH2 0x1e0 MSTORE PUSH2 0x1e0 MLOAD PUSH13 0x1431e0fae6d7217ca9fffffff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL PUSH1 0x5 ADD DUP1 SLOAD PUSH2 0x200 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x220 MSTORE PUSH1 0x2 DUP2 ADD SLOAD PUSH2 0x240 MSTORE PUSH1 0x3 DUP2 ADD SLOAD PUSH2 0x260 MSTORE POP PUSH0 PUSH2 0x280 MSTORE PUSH2 0x1c0 MLOAD PUSH2 0x1e0 MLOAD LT PUSH2 0x172e JUMPI NUMBER PUSH2 0x260 MLOAD EQ PUSH2 0x17ef JUMPI PUSH1 0x4 CALLDATALOAD PUSH2 0x260 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP TIMESTAMP PUSH2 0x240 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 DUP3 MUL DUP2 ISZERO DUP4 DUP4 DUP4 DIV EQ OR ISZERO PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP NUMBER PUSH2 0x260 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 ISZERO PUSH2 0x240a JUMPI DUP1 DUP3 DIV SWAP1 POP SWAP1 POP PUSH2 0x280 MSTORE PUSH2 0x17ef JUMP JUMPDEST PUSH2 0x1e0 MLOAD PUSH1 0x1 DUP2 ADD DUP2 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP PUSH13 0x1431e0fae6d7217ca9fffffff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL PUSH1 0x5 ADD DUP1 SLOAD PUSH2 0x2a0 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x2c0 MSTORE PUSH1 0x2 DUP2 ADD SLOAD PUSH2 0x2e0 MSTORE PUSH1 0x3 DUP2 ADD SLOAD PUSH2 0x300 MSTORE POP PUSH2 0x300 MLOAD PUSH2 0x260 MLOAD EQ PUSH2 0x17ef JUMPI PUSH1 0x4 CALLDATALOAD PUSH2 0x260 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x2e0 MLOAD PUSH2 0x240 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 DUP3 MUL DUP2 ISZERO DUP4 DUP4 DUP4 DIV EQ OR ISZERO PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x300 MLOAD PUSH2 0x260 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 ISZERO PUSH2 0x240a JUMPI DUP1 DUP3 DIV SWAP1 POP SWAP1 POP PUSH2 0x280 MSTORE JUMPDEST PUSH1 0x20 PUSH2 0x200 MLOAD PUSH1 0x40 MSTORE PUSH2 0x220 MLOAD PUSH1 0x60 MSTORE PUSH2 0x240 MLOAD PUSH1 0x80 MSTORE PUSH2 0x260 MLOAD PUSH1 0xa0 MSTORE PUSH2 0x240 MLOAD PUSH2 0x280 MLOAD DUP1 DUP3 ADD DUP3 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH1 0xc0 MSTORE PUSH2 0x1831 PUSH2 0x2a0 PUSH2 0x22a2 JUMP JUMPDEST PUSH2 0x2a0 RETURN JUMPDEST PUSH4 0x3cebb823 DUP2 XOR PUSH2 0x1880 JUMPI PUSH1 0x24 CALLDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x4 CALLDATALOAD DUP1 PUSH1 0xa0 SHR PUSH2 0x240a JUMPI PUSH1 0x40 MSTORE PUSH13 0x50c783eb9b5c85f2a80000008 SLOAD CALLER XOR PUSH2 0x240a JUMPI PUSH1 0x40 MLOAD PUSH13 0x50c783eb9b5c85f2a80000008 SSTORE STOP JUMPDEST POP JUMPDEST PUSH0 PUSH0 REVERT JUMPDEST ORIGIN PUSH1 0x40 MLOAD EQ PUSH2 0x1977 JUMPI PUSH13 0x50c783eb9b5c85f2a80000013 SLOAD PUSH1 0x60 MSTORE PUSH1 0x60 MLOAD ISZERO PUSH2 0x18f7 JUMPI PUSH1 0x60 MLOAD PUSH4 0xc23697a8 PUSH1 0x80 MSTORE PUSH1 0x40 MLOAD PUSH1 0xa0 MSTORE PUSH1 0x20 PUSH1 0x80 PUSH1 0x24 PUSH1 0x9c PUSH0 DUP6 GAS CALL PUSH2 0x18d2 JUMPI RETURNDATASIZE PUSH0 PUSH0 RETURNDATACOPY RETURNDATASIZE PUSH0 REVERT JUMPDEST PUSH1 0x20 RETURNDATASIZE LT PUSH2 0x240a JUMPI PUSH1 0x80 MLOAD DUP1 PUSH1 0x1 SHR PUSH2 0x240a JUMPI PUSH1 0xc0 MSTORE PUSH1 0xc0 SWAP1 POP MLOAD ISZERO PUSH2 0x18f7 JUMPI PUSH2 0x1977 JUMP JUMPDEST PUSH1 0x25 PUSH1 0x80 MSTORE PUSH32 0x536d61727420636f6e7472616374206465706f7369746f7273206e6f7420616c PUSH1 0xa0 MSTORE PUSH32 0x6c6f776564000000000000000000000000000000000000000000000000000000 PUSH1 0xc0 MSTORE PUSH1 0x80 POP PUSH1 0x80 MLOAD DUP1 PUSH1 0xa0 ADD PUSH1 0x1f DUP3 PUSH0 SUB AND CALLDATASIZE DUP3 CALLDATACOPY POP POP PUSH4 0x8c379a0 PUSH1 0x40 MSTORE PUSH1 0x20 PUSH1 0x60 MSTORE PUSH1 0x1f NOT PUSH1 0x1f PUSH1 0x80 MLOAD ADD AND PUSH1 0x44 ADD PUSH1 0x5c REVERT JUMPDEST JUMP JUMPDEST PUSH2 0x140 CALLDATASIZE PUSH1 0xe0 CALLDATACOPY PUSH1 0x4 SLOAD PUSH2 0x220 MSTORE PUSH1 0x40 MLOAD ISZERO PUSH2 0x1aad JUMPI TIMESTAMP PUSH1 0x80 MLOAD GT PUSH2 0x199e JUMPI PUSH0 PUSH2 0x19a6 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x60 MLOAD SLT ISZERO JUMPDEST ISZERO PUSH2 0x19ee JUMPI PUSH1 0x60 MLOAD PUSH4 0x784ce00 DUP2 SDIV SWAP1 POP PUSH2 0x100 MSTORE PUSH2 0x100 MLOAD PUSH1 0x80 MLOAD TIMESTAMP DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 PUSH1 0x7f SHR PUSH2 0x240a JUMPI DUP1 DUP3 MUL DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH1 0xe0 MSTORE JUMPDEST TIMESTAMP PUSH1 0xc0 MLOAD GT PUSH2 0x19fd JUMPI PUSH0 PUSH2 0x1a05 JUMP JUMPDEST PUSH1 0x1 PUSH1 0xa0 MLOAD SLT ISZERO JUMPDEST ISZERO PUSH2 0x1a4e JUMPI PUSH1 0xa0 MLOAD PUSH4 0x784ce00 DUP2 SDIV SWAP1 POP PUSH2 0x180 MSTORE PUSH2 0x180 MLOAD PUSH1 0xc0 MLOAD TIMESTAMP DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 PUSH1 0x7f SHR PUSH2 0x240a JUMPI DUP1 DUP3 MUL DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x160 MSTORE JUMPDEST PUSH13 0x50c783eb9b5c85f2a80000007 PUSH1 0x80 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SLOAD PUSH2 0x1e0 MSTORE PUSH1 0xc0 MLOAD ISZERO PUSH2 0x1aad JUMPI PUSH1 0x80 MLOAD PUSH1 0xc0 MLOAD XOR PUSH2 0x1a8d JUMPI PUSH2 0x1e0 MLOAD PUSH2 0x200 MSTORE PUSH2 0x1aad JUMP JUMPDEST PUSH13 0x50c783eb9b5c85f2a80000007 PUSH1 0xc0 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SLOAD PUSH2 0x200 MSTORE JUMPDEST PUSH1 0x40 CALLDATASIZE PUSH2 0x240 CALLDATACOPY TIMESTAMP PUSH2 0x280 MSTORE NUMBER PUSH2 0x2a0 MSTORE PUSH2 0x220 MLOAD ISZERO PUSH2 0x1b08 JUMPI PUSH2 0x220 MLOAD PUSH13 0x1431e0fae6d7217ca9fffffff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL PUSH1 0x5 ADD DUP1 SLOAD PUSH2 0x240 MSTORE PUSH1 0x1 DUP2 ADD SLOAD PUSH2 0x260 MSTORE PUSH1 0x2 DUP2 ADD SLOAD PUSH2 0x280 MSTORE PUSH1 0x3 DUP2 ADD SLOAD PUSH2 0x2a0 MSTORE POP JUMPDEST PUSH2 0x280 MLOAD PUSH2 0x2c0 MSTORE PUSH2 0x240 MLOAD PUSH2 0x2e0 MSTORE PUSH2 0x260 MLOAD PUSH2 0x300 MSTORE PUSH2 0x280 MLOAD PUSH2 0x320 MSTORE PUSH2 0x2a0 MLOAD PUSH2 0x340 MSTORE PUSH0 PUSH2 0x360 MSTORE PUSH2 0x280 MLOAD TIMESTAMP GT ISZERO PUSH2 0x1b96 JUMPI NUMBER PUSH2 0x2a0 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH8 0xde0b6b3a7640000 DUP2 MUL DUP2 PUSH8 0xde0b6b3a7640000 DUP3 DIV XOR PUSH2 0x240a JUMPI SWAP1 POP TIMESTAMP PUSH2 0x280 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 ISZERO PUSH2 0x240a JUMPI DUP1 DUP3 DIV SWAP1 POP SWAP1 POP PUSH2 0x360 MSTORE JUMPDEST PUSH2 0x2c0 MLOAD PUSH3 0x93a80 DUP2 DIV SWAP1 POP PUSH3 0x93a80 DUP2 MUL DUP2 PUSH3 0x93a80 DUP3 DIV XOR PUSH2 0x240a JUMPI SWAP1 POP PUSH2 0x380 MSTORE PUSH0 PUSH1 0xff SWAP1 JUMPDEST DUP1 PUSH2 0x3a0 MSTORE PUSH2 0x380 MLOAD PUSH3 0x93a80 DUP2 ADD DUP2 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP PUSH2 0x380 MSTORE PUSH0 PUSH2 0x3c0 MSTORE TIMESTAMP PUSH2 0x380 MLOAD GT PUSH2 0x1c0f JUMPI PUSH13 0x50c783eb9b5c85f2a80000007 PUSH2 0x380 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SLOAD PUSH2 0x3c0 MSTORE PUSH2 0x1c15 JUMP JUMPDEST TIMESTAMP PUSH2 0x380 MSTORE JUMPDEST PUSH2 0x240 MLOAD PUSH2 0x260 MLOAD PUSH2 0x380 MLOAD PUSH2 0x2c0 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 PUSH1 0x7f SHR PUSH2 0x240a JUMPI DUP1 DUP3 MUL DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 DUP3 SUB DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x240 MSTORE PUSH2 0x260 MLOAD PUSH2 0x3c0 MLOAD DUP1 DUP3 ADD DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x260 MSTORE PUSH32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff PUSH2 0x240 MLOAD SGT PUSH2 0x1cae JUMPI PUSH0 PUSH2 0x240 MSTORE JUMPDEST PUSH32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff PUSH2 0x260 MLOAD SGT PUSH2 0x1cde JUMPI PUSH0 PUSH2 0x260 MSTORE JUMPDEST PUSH2 0x380 MLOAD PUSH2 0x2c0 MSTORE PUSH2 0x380 MLOAD PUSH2 0x280 MSTORE PUSH2 0x340 MLOAD PUSH2 0x360 MLOAD PUSH2 0x380 MLOAD PUSH2 0x320 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 DUP3 MUL DUP2 ISZERO DUP4 DUP4 DUP4 DIV EQ OR ISZERO PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH8 0xde0b6b3a7640000 DUP2 DIV SWAP1 POP DUP1 DUP3 ADD DUP3 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x2a0 MSTORE PUSH2 0x220 MLOAD PUSH1 0x1 DUP2 ADD DUP2 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP PUSH2 0x220 MSTORE TIMESTAMP PUSH2 0x380 MLOAD XOR PUSH2 0x1d68 JUMPI NUMBER PUSH2 0x2a0 MSTORE PUSH2 0x1db3 JUMP JUMPDEST PUSH2 0x220 MLOAD PUSH13 0x1431e0fae6d7217ca9fffffff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL PUSH1 0x5 ADD PUSH2 0x240 MLOAD DUP2 SSTORE PUSH2 0x260 MLOAD PUSH1 0x1 DUP3 ADD SSTORE PUSH2 0x280 MLOAD PUSH1 0x2 DUP3 ADD SSTORE PUSH2 0x2a0 MLOAD PUSH1 0x3 DUP3 ADD SSTORE POP PUSH1 0x1 ADD DUP2 DUP2 XOR PUSH2 0x1bbf JUMPI JUMPDEST POP POP PUSH2 0x220 MLOAD PUSH1 0x4 SSTORE PUSH1 0x40 MLOAD ISZERO PUSH2 0x1e87 JUMPI PUSH2 0x260 MLOAD PUSH2 0x180 MLOAD PUSH2 0x100 MLOAD DUP1 DUP3 SUB DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 DUP3 ADD DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x260 MSTORE PUSH2 0x240 MLOAD PUSH2 0x160 MLOAD PUSH1 0xe0 MLOAD DUP1 DUP3 SUB DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 DUP3 ADD DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x240 MSTORE PUSH32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff PUSH2 0x260 MLOAD SGT PUSH2 0x1e57 JUMPI PUSH0 PUSH2 0x260 MSTORE JUMPDEST PUSH32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff PUSH2 0x240 MLOAD SGT PUSH2 0x1e87 JUMPI PUSH0 PUSH2 0x240 MSTORE JUMPDEST PUSH2 0x220 MLOAD PUSH13 0x1431e0fae6d7217ca9fffffff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL PUSH1 0x5 ADD PUSH2 0x240 MLOAD DUP2 SSTORE PUSH2 0x260 MLOAD PUSH1 0x1 DUP3 ADD SSTORE PUSH2 0x280 MLOAD PUSH1 0x2 DUP3 ADD SSTORE PUSH2 0x2a0 MLOAD PUSH1 0x3 DUP3 ADD SSTORE POP PUSH1 0x40 MLOAD ISZERO PUSH2 0x203a JUMPI TIMESTAMP PUSH1 0x80 MLOAD GT ISZERO PUSH2 0x1f3f JUMPI PUSH2 0x1e0 MLOAD PUSH2 0x100 MLOAD DUP1 DUP3 ADD DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x1e0 MSTORE PUSH1 0x80 MLOAD PUSH1 0xc0 MLOAD XOR PUSH2 0x1f1f JUMPI PUSH2 0x1e0 MLOAD PUSH2 0x180 MLOAD DUP1 DUP3 SUB DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x1e0 MSTORE JUMPDEST PUSH2 0x1e0 MLOAD PUSH13 0x50c783eb9b5c85f2a80000007 PUSH1 0x80 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SSTORE JUMPDEST TIMESTAMP PUSH1 0xc0 MLOAD GT ISZERO PUSH2 0x1f92 JUMPI PUSH1 0x80 MLOAD PUSH1 0xc0 MLOAD GT ISZERO PUSH2 0x1f92 JUMPI PUSH2 0x200 MLOAD PUSH2 0x180 MLOAD DUP1 DUP3 SUB DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x200 MSTORE PUSH2 0x200 MLOAD PUSH13 0x50c783eb9b5c85f2a80000007 PUSH1 0xc0 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SSTORE JUMPDEST PUSH13 0x50c783eb9b5c85f2a80000006 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SLOAD PUSH1 0x1 DUP2 ADD DUP2 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP PUSH2 0x3a0 MSTORE PUSH2 0x3a0 MLOAD PUSH13 0x50c783eb9b5c85f2a80000006 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SSTORE TIMESTAMP PUSH2 0x1a0 MSTORE NUMBER PUSH2 0x1c0 MSTORE PUSH13 0x50c783eb9b5c85f2a80000005 PUSH1 0x40 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK PUSH2 0x3a0 MLOAD PUSH4 0x3b9ac9ff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL DUP2 ADD SWAP1 POP PUSH2 0x160 MLOAD DUP2 SSTORE PUSH2 0x180 MLOAD PUSH1 0x1 DUP3 ADD SSTORE PUSH2 0x1a0 MLOAD PUSH1 0x2 DUP3 ADD SSTORE PUSH2 0x1c0 MLOAD PUSH1 0x3 DUP3 ADD SSTORE POP JUMPDEST JUMP JUMPDEST PUSH2 0x440 MLOAD PUSH2 0x4a0 MSTORE PUSH2 0x460 MLOAD PUSH2 0x4c0 MSTORE PUSH1 0x2 SLOAD PUSH2 0x4e0 MSTORE PUSH2 0x4e0 MLOAD PUSH2 0x400 MLOAD DUP1 DUP3 ADD DUP3 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH1 0x2 SSTORE PUSH2 0x4a0 MLOAD PUSH2 0x500 MSTORE PUSH2 0x4c0 MLOAD PUSH2 0x520 MSTORE PUSH2 0x4a0 MLOAD PUSH2 0x400 MLOAD DUP1 PUSH1 0x7f SHR PUSH2 0x240a JUMPI DUP1 DUP3 ADD DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x4a0 MSTORE PUSH2 0x420 MLOAD ISZERO PUSH2 0x20b3 JUMPI PUSH2 0x420 MLOAD PUSH2 0x4c0 MSTORE JUMPDEST PUSH1 0x3 PUSH2 0x3e0 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK PUSH2 0x4a0 MLOAD DUP2 SSTORE PUSH2 0x4c0 MLOAD PUSH1 0x1 DUP3 ADD SSTORE POP PUSH2 0x3e0 MLOAD PUSH1 0x40 MSTORE PUSH2 0x500 MLOAD PUSH1 0x60 MSTORE PUSH2 0x520 MLOAD PUSH1 0x80 MSTORE PUSH2 0x4a0 MLOAD PUSH1 0xa0 MSTORE PUSH2 0x4c0 MLOAD PUSH1 0xc0 MSTORE PUSH2 0x20fd PUSH2 0x1979 JUMP JUMPDEST PUSH2 0x400 MLOAD ISZERO PUSH2 0x2165 JUMPI PUSH1 0x1 SLOAD PUSH4 0x23b872dd PUSH2 0x540 MSTORE PUSH2 0x3e0 MLOAD PUSH2 0x560 MSTORE ADDRESS PUSH2 0x580 MSTORE PUSH2 0x400 MLOAD PUSH2 0x5a0 MSTORE PUSH1 0x20 PUSH2 0x540 PUSH1 0x64 PUSH2 0x55c PUSH0 DUP6 GAS CALL PUSH2 0x2141 JUMPI RETURNDATASIZE PUSH0 PUSH0 RETURNDATACOPY RETURNDATASIZE PUSH0 REVERT JUMPDEST PUSH1 0x20 RETURNDATASIZE LT PUSH2 0x240a JUMPI PUSH2 0x540 MLOAD DUP1 PUSH1 0x1 SHR PUSH2 0x240a JUMPI PUSH2 0x5c0 MSTORE PUSH2 0x5c0 SWAP1 POP MLOAD ISZERO PUSH2 0x240a JUMPI JUMPDEST PUSH2 0x4c0 MLOAD PUSH2 0x3e0 MLOAD PUSH32 0x4566dfc29f6f11d13a418c26a02bef7c28bae749d4de47e4e6a7cddea6730d59 PUSH2 0x400 MLOAD PUSH2 0x540 MSTORE PUSH2 0x480 MLOAD PUSH2 0x560 MSTORE TIMESTAMP PUSH2 0x580 MSTORE PUSH1 0x60 PUSH2 0x540 LOG3 PUSH32 0x5e2aa66efd74cce82b21852e317e5490d9ecc9e6bb953ae24d90851258cc2f5c PUSH2 0x4e0 MLOAD PUSH2 0x540 MSTORE PUSH2 0x4e0 MLOAD PUSH2 0x400 MLOAD DUP1 DUP3 ADD DUP3 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x560 MSTORE PUSH1 0x40 PUSH2 0x540 LOG1 JUMP JUMPDEST PUSH0 PUSH1 0x80 MSTORE PUSH1 0x60 MLOAD PUSH1 0xa0 MSTORE PUSH0 PUSH1 0x80 SWAP1 JUMPDEST DUP1 PUSH1 0xc0 MSTORE PUSH1 0xa0 MLOAD PUSH1 0x80 MLOAD LT PUSH2 0x2217 JUMPI PUSH2 0x2298 JUMP JUMPDEST PUSH1 0x80 MLOAD PUSH1 0xa0 MLOAD DUP1 DUP3 ADD DUP3 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH1 0x1 DUP2 ADD DUP2 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP DUP1 PUSH1 0x1 SHR SWAP1 POP PUSH1 0xe0 MSTORE PUSH1 0x40 MLOAD PUSH1 0xe0 MLOAD PUSH13 0x1431e0fae6d7217ca9fffffff DUP2 GT PUSH2 0x240a JUMPI PUSH1 0x2 SHL PUSH1 0x5 ADD PUSH1 0x3 DUP2 ADD SWAP1 POP SLOAD GT ISZERO PUSH2 0x2286 JUMPI PUSH1 0xe0 MLOAD PUSH1 0x1 DUP2 SUB DUP2 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP PUSH1 0xa0 MSTORE PUSH2 0x228d JUMP JUMPDEST PUSH1 0xe0 MLOAD PUSH1 0x80 MSTORE JUMPDEST PUSH1 0x1 ADD DUP2 DUP2 XOR PUSH2 0x2203 JUMPI JUMPDEST POP POP PUSH1 0x80 MLOAD DUP2 MSTORE POP JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0xe0 MSTORE PUSH1 0x60 MLOAD PUSH2 0x100 MSTORE PUSH1 0x80 MLOAD PUSH2 0x120 MSTORE PUSH1 0xa0 MLOAD PUSH2 0x140 MSTORE PUSH2 0x120 MLOAD PUSH3 0x93a80 DUP2 DIV SWAP1 POP PUSH3 0x93a80 DUP2 MUL DUP2 PUSH3 0x93a80 DUP3 DIV XOR PUSH2 0x240a JUMPI SWAP1 POP PUSH2 0x160 MSTORE PUSH0 PUSH1 0xff SWAP1 JUMPDEST DUP1 PUSH2 0x180 MSTORE PUSH2 0x160 MLOAD PUSH3 0x93a80 DUP2 ADD DUP2 DUP2 LT PUSH2 0x240a JUMPI SWAP1 POP PUSH2 0x160 MSTORE PUSH0 PUSH2 0x1a0 MSTORE PUSH1 0xc0 MLOAD PUSH2 0x160 MLOAD GT PUSH2 0x2338 JUMPI PUSH13 0x50c783eb9b5c85f2a80000007 PUSH2 0x160 MLOAD PUSH1 0x20 MSTORE PUSH0 MSTORE PUSH1 0x40 PUSH0 KECCAK SLOAD PUSH2 0x1a0 MSTORE PUSH2 0x2340 JUMP JUMPDEST PUSH1 0xc0 MLOAD PUSH2 0x160 MSTORE JUMPDEST PUSH1 0xe0 MLOAD PUSH2 0x100 MLOAD PUSH2 0x160 MLOAD PUSH2 0x120 MLOAD DUP1 DUP3 SUB DUP3 DUP2 GT PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 PUSH1 0x7f SHR PUSH2 0x240a JUMPI DUP1 DUP3 MUL DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP DUP1 DUP3 SUB DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH1 0xe0 MSTORE PUSH1 0xc0 MLOAD PUSH2 0x160 MLOAD XOR PUSH2 0x239b JUMPI PUSH2 0x23cb JUMP JUMPDEST PUSH2 0x100 MLOAD PUSH2 0x1a0 MLOAD DUP1 DUP3 ADD DUP1 PUSH1 0xf SIGNEXTEND DUP2 XOR PUSH2 0x240a JUMPI SWAP1 POP SWAP1 POP PUSH2 0x100 MSTORE PUSH2 0x160 MLOAD PUSH2 0x120 MSTORE PUSH1 0x1 ADD DUP2 DUP2 XOR PUSH2 0x22e6 JUMPI JUMPDEST POP POP PUSH32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff PUSH1 0xe0 MLOAD SGT PUSH2 0x23fb JUMPI PUSH0 PUSH1 0xe0 MSTORE JUMPDEST PUSH1 0xe0 MLOAD PUSH0 DUP2 SLT PUSH2 0x240a JUMPI DUP2 MSTORE POP JUMP JUMPDEST PUSH0 DUP1 REVERT'

    Precompiles

    Precompiles are special contracts that are implemented using native code. We can devise a pattern to find their usage after looking at how the compiler calls them15.

  • 15 See ecadd implementation

  • PRECOMPILES = {
        "0x1": "ecrecover",
        "0x2": "sha256",
        "0x3": "ripemd160",
        "0x4": "identity",
        "0x5": "modexp",
        "0x6": "alt_bn128_add",
        "0x7": "alt_bn128_mul",
        "0x8": "alt_bn128_pairing_check",
        "0x9": "blake2f",
    }
    PRECOMPILE_REGEX = r"PUSH1 (0x[1-9]) GAS STATICCALL"
    
    
    def get_precompiles(code):
        opcodes = disasm(code)
        extracted = re.findall(PRECOMPILE_REGEX, opcodes)
        return [PRECOMPILES.get(x, x) for x in extracted]
    
    
    (
        vypers.with_columns(precompiles=pl.col("clean_code").apply(get_precompiles))
        .explode("precompiles")
        .groupby("precompiles")
        .agg(pl.count())
        .filter(pl.col("precompiles").is_not_null())
        .sort("count", descending=True)
    )
    shape: (3, 2)
    precompiles count
    str u32
    "identity" 5690
    "ecrecover" 299
    "sha256" 2

    At this point we have full assurance that nobody has ever used Vyper for moon math.

    Opcodes

    Our pipeline has reached its full potential, and we can easily repeat the scan for opcodes in question16.

  • 16 See uint256_addmod and uint256_mulmod implementation

  • OPCODE_REGEX = r"ADDMOD|MULMOD"
    
    
    def get_opcodes(code):
        opcodes = disasm(code)
        extracted = re.findall(OPCODE_REGEX, opcodes)
        return sorted(set(extracted))
    
    
    (
        vypers.with_columns(opcodes=pl.col("clean_code").apply(get_opcodes))
        .filter(pl.col("opcodes").list.lengths() > 0)
        .with_columns(
            pl.col(pl.Binary).bin.encode("hex"), pl.col("opcodes").list.join(", ")
        )
        .select(["contract_address", "deployer", "opcodes"])
    )
    shape: (7, 3)
    contract_address deployer opcodes
    str str str
    "53cc3e49418380e835fc8cacd5932482c586efea" "e6da683076b7ed6ce7ec972f21eb8f91e9137a17" "MULMOD"
    "66442b0c5260b92caa9c234ecf2408cbf6b19a6f" "e6da683076b7ed6ce7ec972f21eb8f91e9137a17" "MULMOD"
    "5fc124a161d888893529f67580ef94c2784e9233" "e6da683076b7ed6ce7ec972f21eb8f91e9137a17" "MULMOD"
    "ab595f0bf1d7787a0a39243074a820378afe1504" "bc210cc8c2bb0400c80196b6d47d6b2875cab3bd" "MULMOD"
    "c742904b04193d36b1f93255f98dc9ed2ca4c2aa" "bc210cc8c2bb0400c80196b6d47d6b2875cab3bd" "MULMOD"
    "80333bd8791fee04c4c3e1ca8a524cefa7c94737" "babe61887f1de2713c6f97e567623453d3c79f67" "MULMOD"
    "7624c0dd4f5d06d650ddff25ffec45d032501260" "babe61887f1de2713c6f97e567623453d3c79f67" "MULMOD"

    Resolution

    Good news, we have narrowed the results down to just 0.2% of our initial search, and it’s easy to assess by hand from there.

    Among several unverified contracts we find one Curve contract17 that uses uint256_mulmod. I promptly contact the devs and get a confirmation it’s a discarded test iteration and not a production contract. It wouldn’t have been vulnerable anyway since the issue only affects the order of evaluation of side effects and not the order of arguments themselves, which would’ve likely been caught by tests.

  • 17 It is always a good idea to add a natspec for @author

  • With this work done, we have established with absolute certainty that no production contract is affected and the devs can safely proceed with disclosing the bug.