Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
5389674 | 288 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
MIPS
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 999999 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol"; import { PreimageKeyLib } from "./PreimageKeyLib.sol"; /// @title MIPS /// @notice The MIPS contract emulates a single MIPS instruction. /// Note that delay slots are isolated instructions: /// the nextPC in the state pre-schedules where the VM jumps next. /// The Step input is a packed VM state, with binary-merkle-tree /// witness data for memory reads/writes. /// The Step outputs a keccak256 hash of the packed VM State, /// and logs the resulting state for offchain usage. /// @dev https://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_Green_Sheet.pdf /// @dev https://www.cs.cmu.edu/afs/cs/academic/class/15740-f97/public/doc/mips-isa.pdf /// (page A-177) /// @dev https://uweb.engr.arizona.edu/~ece369/Resources/spim/MIPSReference.pdf /// @dev https://en.wikibooks.org/wiki/MIPS_Assembly/Instruction_Formats /// @dev https://github.com/golang/go/blob/master/src/syscall/zerrors_linux_mips.go /// MIPS linux kernel errors used by Go runtime contract MIPS { /// @notice Stores the VM state. /// Total state size: 32 + 32 + 6 * 4 + 1 + 1 + 8 + 32 * 4 = 226 bytes /// If nextPC != pc + 4, then the VM is executing a branch/jump delay slot. struct State { bytes32 memRoot; bytes32 preimageKey; uint32 preimageOffset; uint32 pc; uint32 nextPC; uint32 lo; uint32 hi; uint32 heap; uint8 exitCode; bool exited; uint64 step; uint32[32] registers; } /// @notice Start of the data segment. uint32 public constant BRK_START = 0x40000000; uint32 constant FD_STDIN = 0; uint32 constant FD_STDOUT = 1; uint32 constant FD_STDERR = 2; uint32 constant FD_HINT_READ = 3; uint32 constant FD_HINT_WRITE = 4; uint32 constant FD_PREIMAGE_READ = 5; uint32 constant FD_PREIMAGE_WRITE = 6; uint32 constant EBADF = 0x9; uint32 constant EINVAL = 0x16; /// @notice The preimage oracle contract. IPreimageOracle internal immutable ORACLE; /// @param _oracle The address of the preimage oracle contract. constructor(IPreimageOracle _oracle) { ORACLE = _oracle; } /// @notice Getter for the pre-image oracle contract. /// @return oracle_ The IPreimageOracle contract. function oracle() external view returns (IPreimageOracle oracle_) { oracle_ = ORACLE; } /// @notice Extends the value leftwards with its most significant bit (sign extension). function SE(uint32 _dat, uint32 _idx) internal pure returns (uint32 out_) { unchecked { bool isSigned = (_dat >> (_idx - 1)) != 0; uint256 signed = ((1 << (32 - _idx)) - 1) << _idx; uint256 mask = (1 << _idx) - 1; return uint32(_dat & mask | (isSigned ? signed : 0)); } } /// @notice Computes the hash of the MIPS state. /// @return out_ The hashed MIPS state. function outputState() internal returns (bytes32 out_) { assembly { // copies 'size' bytes, right-aligned in word at 'from', to 'to', incl. trailing data function copyMem(from, to, size) -> fromOut, toOut { mstore(to, mload(add(from, sub(32, size)))) fromOut := add(from, 32) toOut := add(to, size) } // From points to the MIPS State let from := 0x80 // Copy to the free memory pointer let start := mload(0x40) let to := start // Copy state to free memory from, to := copyMem(from, to, 32) // memRoot from, to := copyMem(from, to, 32) // preimageKey from, to := copyMem(from, to, 4) // preimageOffset from, to := copyMem(from, to, 4) // pc from, to := copyMem(from, to, 4) // nextPC from, to := copyMem(from, to, 4) // lo from, to := copyMem(from, to, 4) // hi from, to := copyMem(from, to, 4) // heap let exitCode := mload(from) from, to := copyMem(from, to, 1) // exitCode let exited := mload(from) from, to := copyMem(from, to, 1) // exited from, to := copyMem(from, to, 8) // step from := add(from, 32) // offset to registers // Copy registers for { let i := 0 } lt(i, 32) { i := add(i, 1) } { from, to := copyMem(from, to, 4) } // Clean up end of memory mstore(to, 0) // Log the resulting MIPS state, for debugging log0(start, sub(to, start)) // Determine the VM status let status := 0 switch exited case 1 { switch exitCode // VMStatusValid case 0 { status := 0 } // VMStatusInvalid case 1 { status := 1 } // VMStatusPanic default { status := 2 } } // VMStatusUnfinished default { status := 3 } // Compute the hash of the resulting MIPS state and set the status byte out_ := keccak256(start, sub(to, start)) out_ := or(and(not(shl(248, 0xFF)), out_), shl(248, status)) } } /// @notice Handles a syscall. /// @param _localContext The local key context for the preimage oracle. /// @return out_ The hashed MIPS state. function handleSyscall(bytes32 _localContext) internal returns (bytes32 out_) { unchecked { // Load state from memory State memory state; assembly { state := 0x80 } // Load the syscall number from the registers uint32 syscall_no = state.registers[2]; uint32 v0 = 0; uint32 v1 = 0; // Load the syscall arguments from the registers uint32 a0 = state.registers[4]; uint32 a1 = state.registers[5]; uint32 a2 = state.registers[6]; // mmap: Allocates a page from the heap. if (syscall_no == 4090) { uint32 sz = a1; if (sz & 4095 != 0) { // adjust size to align with page size sz += 4096 - (sz & 4095); } if (a0 == 0) { v0 = state.heap; state.heap += sz; } else { v0 = a0; } } // brk: Returns a fixed address for the program break at 0x40000000 else if (syscall_no == 4045) { v0 = BRK_START; } // clone (not supported) returns 1 else if (syscall_no == 4120) { v0 = 1; } // exit group: Sets the Exited and ExitCode states to true and argument 0. else if (syscall_no == 4246) { state.exited = true; state.exitCode = uint8(a0); return outputState(); } // read: Like Linux read syscall. Splits unaligned reads into aligned reads. else if (syscall_no == 4003) { // args: a0 = fd, a1 = addr, a2 = count // returns: v0 = read, v1 = err code if (a0 == FD_STDIN) { // Leave v0 and v1 zero: read nothing, no error } // pre-image oracle read else if (a0 == FD_PREIMAGE_READ) { // verify proof 1 is correct, and get the existing memory. uint32 mem = readMem(a1 & 0xFFffFFfc, 1); // mask the addr to align it to 4 bytes bytes32 preimageKey = state.preimageKey; // If the preimage key is a local key, localize it in the context of the caller. if (uint8(preimageKey[0]) == 1) { preimageKey = PreimageKeyLib.localize(preimageKey, _localContext); } (bytes32 dat, uint256 datLen) = ORACLE.readPreimage(preimageKey, state.preimageOffset); // Transform data for writing to memory // We use assembly for more precise ops, and no var count limit assembly { let alignment := and(a1, 3) // the read might not start at an aligned address let space := sub(4, alignment) // remaining space in memory word if lt(space, datLen) { datLen := space } // if less space than data, shorten data if lt(a2, datLen) { datLen := a2 } // if requested to read less, read less dat := shr(sub(256, mul(datLen, 8)), dat) // right-align data dat := shl(mul(sub(sub(4, datLen), alignment), 8), dat) // position data to insert into memory // word let mask := sub(shl(mul(sub(4, alignment), 8), 1), 1) // mask all bytes after start let suffixMask := sub(shl(mul(sub(sub(4, alignment), datLen), 8), 1), 1) // mask of all bytes // starting from end, maybe none mask := and(mask, not(suffixMask)) // reduce mask to just cover the data we insert mem := or(and(mem, not(mask)), dat) // clear masked part of original memory, and insert data } // Write memory back writeMem(a1 & 0xFFffFFfc, 1, mem); state.preimageOffset += uint32(datLen); v0 = uint32(datLen); } // hint response else if (a0 == FD_HINT_READ) { // Don't read into memory, just say we read it all // The result is ignored anyway v0 = a2; } else { v0 = 0xFFffFFff; v1 = EBADF; } } // write: like Linux write syscall. Splits unaligned writes into aligned writes. else if (syscall_no == 4004) { // args: a0 = fd, a1 = addr, a2 = count // returns: v0 = written, v1 = err code if (a0 == FD_STDOUT || a0 == FD_STDERR || a0 == FD_HINT_WRITE) { v0 = a2; // tell program we have written everything } // pre-image oracle else if (a0 == FD_PREIMAGE_WRITE) { uint32 mem = readMem(a1 & 0xFFffFFfc, 1); // mask the addr to align it to 4 bytes bytes32 key = state.preimageKey; // Construct pre-image key from memory // We use assembly for more precise ops, and no var count limit assembly { let alignment := and(a1, 3) // the read might not start at an aligned address let space := sub(4, alignment) // remaining space in memory word if lt(space, a2) { a2 := space } // if less space than data, shorten data key := shl(mul(a2, 8), key) // shift key, make space for new info let mask := sub(shl(mul(a2, 8), 1), 1) // mask for extracting value from memory mem := and(shr(mul(sub(space, a2), 8), mem), mask) // align value to right, mask it key := or(key, mem) // insert into key } // Write pre-image key to oracle state.preimageKey = key; state.preimageOffset = 0; // reset offset, to read new pre-image data from the start v0 = a2; } else { v0 = 0xFFffFFff; v1 = EBADF; } } // fcntl: Like linux fcntl syscall, but only supports minimal file-descriptor control commands, // to retrieve the file-descriptor R/W flags. else if (syscall_no == 4055) { // fcntl // args: a0 = fd, a1 = cmd if (a1 == 3) { // F_GETFL: get file descriptor flags if (a0 == FD_STDIN || a0 == FD_PREIMAGE_READ || a0 == FD_HINT_READ) { v0 = 0; // O_RDONLY } else if (a0 == FD_STDOUT || a0 == FD_STDERR || a0 == FD_PREIMAGE_WRITE || a0 == FD_HINT_WRITE) { v0 = 1; // O_WRONLY } else { v0 = 0xFFffFFff; v1 = EBADF; } } else { v0 = 0xFFffFFff; v1 = EINVAL; // cmd not recognized by this kernel } } // Write the results back to the state registers state.registers[2] = v0; state.registers[7] = v1; // Update the PC and nextPC state.pc = state.nextPC; state.nextPC = state.nextPC + 4; out_ = outputState(); } } /// @notice Handles a branch instruction, updating the MIPS state PC where needed. /// @param _opcode The opcode of the branch instruction. /// @param _insn The instruction to be executed. /// @param _rtReg The register to be used for the branch. /// @param _rs The register to be compared with the branch register. /// @return out_ The hashed MIPS state. function handleBranch(uint32 _opcode, uint32 _insn, uint32 _rtReg, uint32 _rs) internal returns (bytes32 out_) { unchecked { // Load state from memory State memory state; assembly { state := 0x80 } bool shouldBranch = false; if (state.nextPC != state.pc + 4) { revert("branch in delay slot"); } // beq/bne: Branch on equal / not equal if (_opcode == 4 || _opcode == 5) { uint32 rt = state.registers[_rtReg]; shouldBranch = (_rs == rt && _opcode == 4) || (_rs != rt && _opcode == 5); } // blez: Branches if instruction is less than or equal to zero else if (_opcode == 6) { shouldBranch = int32(_rs) <= 0; } // bgtz: Branches if instruction is greater than zero else if (_opcode == 7) { shouldBranch = int32(_rs) > 0; } // bltz/bgez: Branch on less than zero / greater than or equal to zero else if (_opcode == 1) { // regimm uint32 rtv = ((_insn >> 16) & 0x1F); if (rtv == 0) { shouldBranch = int32(_rs) < 0; } if (rtv == 1) { shouldBranch = int32(_rs) >= 0; } } // Update the state's previous PC uint32 prevPC = state.pc; // Execute the delay slot first state.pc = state.nextPC; // If we should branch, update the PC to the branch target // Otherwise, proceed to the next instruction if (shouldBranch) { state.nextPC = prevPC + 4 + (SE(_insn & 0xFFFF, 16) << 2); } else { state.nextPC = state.nextPC + 4; } // Return the hash of the resulting state out_ = outputState(); } } /// @notice Handles HI and LO register instructions. /// @param _func The function code of the instruction. /// @param _rs The value of the RS register. /// @param _rt The value of the RT register. /// @param _storeReg The register to store the result in. /// @return out_ The hashed MIPS state. function handleHiLo(uint32 _func, uint32 _rs, uint32 _rt, uint32 _storeReg) internal returns (bytes32 out_) { unchecked { // Load state from memory State memory state; assembly { state := 0x80 } uint32 val; // mfhi: Move the contents of the HI register into the destination if (_func == 0x10) { val = state.hi; } // mthi: Move the contents of the source into the HI register else if (_func == 0x11) { state.hi = _rs; } // mflo: Move the contents of the LO register into the destination else if (_func == 0x12) { val = state.lo; } // mtlo: Move the contents of the source into the LO register else if (_func == 0x13) { state.lo = _rs; } // mult: Multiplies `rs` by `rt` and stores the result in HI and LO registers else if (_func == 0x18) { uint64 acc = uint64(int64(int32(_rs)) * int64(int32(_rt))); state.hi = uint32(acc >> 32); state.lo = uint32(acc); } // multu: Unsigned multiplies `rs` by `rt` and stores the result in HI and LO registers else if (_func == 0x19) { uint64 acc = uint64(uint64(_rs) * uint64(_rt)); state.hi = uint32(acc >> 32); state.lo = uint32(acc); } // div: Divides `rs` by `rt`. // Stores the quotient in LO // And the remainder in HI else if (_func == 0x1a) { state.hi = uint32(int32(_rs) % int32(_rt)); state.lo = uint32(int32(_rs) / int32(_rt)); } // divu: Unsigned divides `rs` by `rt`. // Stores the quotient in LO // And the remainder in HI else if (_func == 0x1b) { state.hi = _rs % _rt; state.lo = _rs / _rt; } // Store the result in the destination register, if applicable if (_storeReg != 0) { state.registers[_storeReg] = val; } // Update the PC state.pc = state.nextPC; state.nextPC = state.nextPC + 4; // Return the hash of the resulting state out_ = outputState(); } } /// @notice Handles a jump instruction, updating the MIPS state PC where needed. /// @param _linkReg The register to store the link to the instruction after the delay slot instruction. /// @param _dest The destination to jump to. /// @return out_ The hashed MIPS state. function handleJump(uint32 _linkReg, uint32 _dest) internal returns (bytes32 out_) { unchecked { // Load state from memory. State memory state; assembly { state := 0x80 } if (state.nextPC != state.pc + 4) { revert("jump in delay slot"); } // Update the next PC to the jump destination. uint32 prevPC = state.pc; state.pc = state.nextPC; state.nextPC = _dest; // Update the link-register to the instruction after the delay slot instruction. if (_linkReg != 0) { state.registers[_linkReg] = prevPC + 8; } // Return the hash of the resulting state. out_ = outputState(); } } /// @notice Handles a storing a value into a register. /// @param _storeReg The register to store the value into. /// @param _val The value to store. /// @param _conditional Whether or not the store is conditional. /// @return out_ The hashed MIPS state. function handleRd(uint32 _storeReg, uint32 _val, bool _conditional) internal returns (bytes32 out_) { unchecked { // Load state from memory. State memory state; assembly { state := 0x80 } // The destination register must be valid. require(_storeReg < 32, "valid register"); // Never write to reg 0, and it can be conditional (movz, movn). if (_storeReg != 0 && _conditional) { state.registers[_storeReg] = _val; } // Update the PC. state.pc = state.nextPC; state.nextPC = state.nextPC + 4; // Return the hash of the resulting state. out_ = outputState(); } } /// @notice Computes the offset of the proof in the calldata. /// @param _proofIndex The index of the proof in the calldata. /// @return offset_ The offset of the proof in the calldata. function proofOffset(uint8 _proofIndex) internal pure returns (uint256 offset_) { unchecked { // A proof of 32 bit memory, with 32-byte leaf values, is (32-5)=27 bytes32 entries. // And the leaf value itself needs to be encoded as well. And proof.offset == 420 offset_ = 420 + (uint256(_proofIndex) * (28 * 32)); uint256 s = 0; assembly { s := calldatasize() } require(s >= (offset_ + 28 * 32), "check that there is enough calldata"); return offset_; } } /// @notice Reads a 32-bit value from memory. /// @param _addr The address to read from. /// @param _proofIndex The index of the proof in the calldata. /// @return out_ The hashed MIPS state. function readMem(uint32 _addr, uint8 _proofIndex) internal pure returns (uint32 out_) { unchecked { // Compute the offset of the proof in the calldata. uint256 offset = proofOffset(_proofIndex); assembly { // Validate the address alignement. if and(_addr, 3) { revert(0, 0) } // Load the leaf value. let leaf := calldataload(offset) offset := add(offset, 32) // Convenience function to hash two nodes together in scratch space. function hashPair(a, b) -> h { mstore(0, a) mstore(32, b) h := keccak256(0, 64) } // Start with the leaf node. // Work back up by combining with siblings, to reconstruct the root. let path := shr(5, _addr) let node := leaf for { let i := 0 } lt(i, 27) { i := add(i, 1) } { let sibling := calldataload(offset) offset := add(offset, 32) switch and(shr(i, path), 1) case 0 { node := hashPair(node, sibling) } case 1 { node := hashPair(sibling, node) } } // Load the memory root from the first field of state. let memRoot := mload(0x80) // Verify the root matches. if iszero(eq(node, memRoot)) { mstore(0, 0x0badf00d) revert(0, 32) } // Bits to shift = (32 - 4 - (addr % 32)) * 8 let shamt := shl(3, sub(sub(32, 4), and(_addr, 31))) out_ := and(shr(shamt, leaf), 0xFFffFFff) } } } /// @notice Writes a 32-bit value to memory. /// This function first overwrites the part of the leaf. /// Then it recomputes the memory merkle root. /// @param _addr The address to write to. /// @param _proofIndex The index of the proof in the calldata. /// @param _val The value to write. function writeMem(uint32 _addr, uint8 _proofIndex, uint32 _val) internal pure { unchecked { // Compute the offset of the proof in the calldata. uint256 offset = proofOffset(_proofIndex); assembly { // Validate the address alignement. if and(_addr, 3) { revert(0, 0) } // Load the leaf value. let leaf := calldataload(offset) let shamt := shl(3, sub(sub(32, 4), and(_addr, 31))) // Mask out 4 bytes, and OR in the value leaf := or(and(leaf, not(shl(shamt, 0xFFffFFff))), shl(shamt, _val)) offset := add(offset, 32) // Convenience function to hash two nodes together in scratch space. function hashPair(a, b) -> h { mstore(0, a) mstore(32, b) h := keccak256(0, 64) } // Start with the leaf node. // Work back up by combining with siblings, to reconstruct the root. let path := shr(5, _addr) let node := leaf for { let i := 0 } lt(i, 27) { i := add(i, 1) } { let sibling := calldataload(offset) offset := add(offset, 32) switch and(shr(i, path), 1) case 0 { node := hashPair(node, sibling) } case 1 { node := hashPair(sibling, node) } } // Store the new memory root in the first field of state. mstore(0x80, node) } } } /// @notice Executes a single step of the vm. /// Will revert if any required input state is missing. /// @param _stateData The encoded state witness data. /// @param _proof The encoded proof data for leaves within the MIPS VM's memory. /// @param _localContext The local key context for the preimage oracle. Optional, can be set as a constant /// if the caller only requires one set of local keys. function step(bytes calldata _stateData, bytes calldata _proof, bytes32 _localContext) public returns (bytes32) { unchecked { State memory state; // Packed calldata is ~6 times smaller than state size assembly { if iszero(eq(state, 0x80)) { // expected state mem offset check revert(0, 0) } if iszero(eq(mload(0x40), shl(5, 48))) { // expected memory check revert(0, 0) } if iszero(eq(_stateData.offset, 132)) { // 32*4+4=132 expected state data offset revert(0, 0) } if iszero(eq(_proof.offset, 420)) { // 132+32+256=420 expected proof offset revert(0, 0) } function putField(callOffset, memOffset, size) -> callOffsetOut, memOffsetOut { // calldata is packed, thus starting left-aligned, shift-right to pad and right-align let w := shr(shl(3, sub(32, size)), calldataload(callOffset)) mstore(memOffset, w) callOffsetOut := add(callOffset, size) memOffsetOut := add(memOffset, 32) } // Unpack state from calldata into memory let c := _stateData.offset // calldata offset let m := 0x80 // mem offset c, m := putField(c, m, 32) // memRoot c, m := putField(c, m, 32) // preimageKey c, m := putField(c, m, 4) // preimageOffset c, m := putField(c, m, 4) // pc c, m := putField(c, m, 4) // nextPC c, m := putField(c, m, 4) // lo c, m := putField(c, m, 4) // hi c, m := putField(c, m, 4) // heap c, m := putField(c, m, 1) // exitCode c, m := putField(c, m, 1) // exited c, m := putField(c, m, 8) // step // Unpack register calldata into memory mstore(m, add(m, 32)) // offset to registers m := add(m, 32) for { let i := 0 } lt(i, 32) { i := add(i, 1) } { c, m := putField(c, m, 4) } } // Don't change state once exited if (state.exited) { return outputState(); } state.step += 1; // instruction fetch uint32 insn = readMem(state.pc, 0); uint32 opcode = insn >> 26; // 6-bits // j-type j/jal if (opcode == 2 || opcode == 3) { // Take top 4 bits of the next PC (its 256 MB region), and concatenate with the 26-bit offset uint32 target = (state.nextPC & 0xF0000000) | (insn & 0x03FFFFFF) << 2; return handleJump(opcode == 2 ? 0 : 31, target); } // register fetch uint32 rs; // source register 1 value uint32 rt; // source register 2 / temp value uint32 rtReg = (insn >> 16) & 0x1F; // R-type or I-type (stores rt) rs = state.registers[(insn >> 21) & 0x1F]; uint32 rdReg = rtReg; if (opcode == 0 || opcode == 0x1c) { // R-type (stores rd) rt = state.registers[rtReg]; rdReg = (insn >> 11) & 0x1F; } else if (opcode < 0x20) { // rt is SignExtImm // don't sign extend for andi, ori, xori if (opcode == 0xC || opcode == 0xD || opcode == 0xe) { // ZeroExtImm rt = insn & 0xFFFF; } else { // SignExtImm rt = SE(insn & 0xFFFF, 16); } } else if (opcode >= 0x28 || opcode == 0x22 || opcode == 0x26) { // store rt value with store rt = state.registers[rtReg]; // store actual rt with lwl and lwr rdReg = rtReg; } if ((opcode >= 4 && opcode < 8) || opcode == 1) { return handleBranch(opcode, insn, rtReg, rs); } uint32 storeAddr = 0xFF_FF_FF_FF; // memory fetch (all I-type) // we do the load for stores also uint32 mem; if (opcode >= 0x20) { // M[R[rs]+SignExtImm] rs += SE(insn & 0xFFFF, 16); uint32 addr = rs & 0xFFFFFFFC; mem = readMem(addr, 1); if (opcode >= 0x28 && opcode != 0x30) { // store storeAddr = addr; // store opcodes don't write back to a register rdReg = 0; } } // ALU uint32 val = execute(insn, rs, rt, mem) & 0xffFFffFF; // swr outputs more than 4 bytes without the mask uint32 func = insn & 0x3f; // 6-bits if (opcode == 0 && func >= 8 && func < 0x1c) { if (func == 8 || func == 9) { // jr/jalr return handleJump(func == 8 ? 0 : rdReg, rs); } if (func == 0xa) { // movz return handleRd(rdReg, rs, rt == 0); } if (func == 0xb) { // movn return handleRd(rdReg, rs, rt != 0); } // syscall (can read and write) if (func == 0xC) { return handleSyscall(_localContext); } // lo and hi registers // can write back if (func >= 0x10 && func < 0x1c) { return handleHiLo(func, rs, rt, rdReg); } } // stupid sc, write a 1 to rt if (opcode == 0x38 && rtReg != 0) { state.registers[rtReg] = 1; } // write memory if (storeAddr != 0xFF_FF_FF_FF) { writeMem(storeAddr, 1, val); } // write back the value to destination register return handleRd(rdReg, val, true); } } /// @notice Execute an instruction. function execute(uint32 insn, uint32 rs, uint32 rt, uint32 mem) internal pure returns (uint32 out) { unchecked { uint32 opcode = insn >> 26; // 6-bits if (opcode == 0 || (opcode >= 8 && opcode < 0xF)) { uint32 func = insn & 0x3f; // 6-bits assembly { // transform ArithLogI to SPECIAL switch opcode // addi case 0x8 { func := 0x20 } // addiu case 0x9 { func := 0x21 } // stli case 0xA { func := 0x2A } // sltiu case 0xB { func := 0x2B } // andi case 0xC { func := 0x24 } // ori case 0xD { func := 0x25 } // xori case 0xE { func := 0x26 } } // sll if (func == 0x00) { return rt << ((insn >> 6) & 0x1F); } // srl else if (func == 0x02) { return rt >> ((insn >> 6) & 0x1F); } // sra else if (func == 0x03) { uint32 shamt = (insn >> 6) & 0x1F; return SE(rt >> shamt, 32 - shamt); } // sllv else if (func == 0x04) { return rt << (rs & 0x1F); } // srlv else if (func == 0x6) { return rt >> (rs & 0x1F); } // srav else if (func == 0x07) { return SE(rt >> rs, 32 - rs); } // functs in range [0x8, 0x1b] are handled specially by other functions // Explicitly enumerate each funct in range to reduce code diff against Go Vm // jr else if (func == 0x08) { return rs; } // jalr else if (func == 0x09) { return rs; } // movz else if (func == 0x0a) { return rs; } // movn else if (func == 0x0b) { return rs; } // syscall else if (func == 0x0c) { return rs; } // 0x0d - break not supported // sync else if (func == 0x0f) { return rs; } // mfhi else if (func == 0x10) { return rs; } // mthi else if (func == 0x11) { return rs; } // mflo else if (func == 0x12) { return rs; } // mtlo else if (func == 0x13) { return rs; } // mult else if (func == 0x18) { return rs; } // multu else if (func == 0x19) { return rs; } // div else if (func == 0x1a) { return rs; } // divu else if (func == 0x1b) { return rs; } // The rest includes transformed R-type arith imm instructions // add else if (func == 0x20) { return (rs + rt); } // addu else if (func == 0x21) { return (rs + rt); } // sub else if (func == 0x22) { return (rs - rt); } // subu else if (func == 0x23) { return (rs - rt); } // and else if (func == 0x24) { return (rs & rt); } // or else if (func == 0x25) { return (rs | rt); } // xor else if (func == 0x26) { return (rs ^ rt); } // nor else if (func == 0x27) { return ~(rs | rt); } // slti else if (func == 0x2a) { return int32(rs) < int32(rt) ? 1 : 0; } // sltiu else if (func == 0x2b) { return rs < rt ? 1 : 0; } else { revert("invalid instruction"); } } else { // SPECIAL2 if (opcode == 0x1C) { uint32 func = insn & 0x3f; // 6-bits // mul if (func == 0x2) { return uint32(int32(rs) * int32(rt)); } // clz, clo else if (func == 0x20 || func == 0x21) { if (func == 0x20) { rs = ~rs; } uint32 i = 0; while (rs & 0x80000000 != 0) { i++; rs <<= 1; } return i; } } // lui else if (opcode == 0x0F) { return rt << 16; } // lb else if (opcode == 0x20) { return SE((mem >> (24 - (rs & 3) * 8)) & 0xFF, 8); } // lh else if (opcode == 0x21) { return SE((mem >> (16 - (rs & 2) * 8)) & 0xFFFF, 16); } // lwl else if (opcode == 0x22) { uint32 val = mem << ((rs & 3) * 8); uint32 mask = uint32(0xFFFFFFFF) << ((rs & 3) * 8); return (rt & ~mask) | val; } // lw else if (opcode == 0x23) { return mem; } // lbu else if (opcode == 0x24) { return (mem >> (24 - (rs & 3) * 8)) & 0xFF; } // lhu else if (opcode == 0x25) { return (mem >> (16 - (rs & 2) * 8)) & 0xFFFF; } // lwr else if (opcode == 0x26) { uint32 val = mem >> (24 - (rs & 3) * 8); uint32 mask = uint32(0xFFFFFFFF) >> (24 - (rs & 3) * 8); return (rt & ~mask) | val; } // sb else if (opcode == 0x28) { uint32 val = (rt & 0xFF) << (24 - (rs & 3) * 8); uint32 mask = 0xFFFFFFFF ^ uint32(0xFF << (24 - (rs & 3) * 8)); return (mem & mask) | val; } // sh else if (opcode == 0x29) { uint32 val = (rt & 0xFFFF) << (16 - (rs & 2) * 8); uint32 mask = 0xFFFFFFFF ^ uint32(0xFFFF << (16 - (rs & 2) * 8)); return (mem & mask) | val; } // swl else if (opcode == 0x2a) { uint32 val = rt >> ((rs & 3) * 8); uint32 mask = uint32(0xFFFFFFFF) >> ((rs & 3) * 8); return (mem & ~mask) | val; } // sw else if (opcode == 0x2b) { return rt; } // swr else if (opcode == 0x2e) { uint32 val = rt << (24 - (rs & 3) * 8); uint32 mask = uint32(0xFFFFFFFF) << (24 - (rs & 3) * 8); return (mem & ~mask) | val; } // ll else if (opcode == 0x30) { return mem; } // sc else if (opcode == 0x38) { return rt; } else { revert("invalid instruction"); } } revert("invalid instruction"); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; /// @title IPreimageOracle /// @notice Interface for a preimage oracle. interface IPreimageOracle { /// @notice Reads a preimage from the oracle. /// @param _key The key of the preimage to read. /// @param _offset The offset of the preimage to read. /// @return dat_ The preimage data. /// @return datLen_ The length of the preimage data. function readPreimage(bytes32 _key, uint256 _offset) external view returns (bytes32 dat_, uint256 datLen_); /// @notice Loads of local data part into the preimage oracle. /// @param _ident The identifier of the local data. /// @param _localContext The local key context for the preimage oracle. Optionally, can be set as a constant /// if the caller only requires one set of local keys. /// @param _word The local data word. /// @param _size The number of bytes in `_word` to load. /// @param _partOffset The offset of the local data part to write to the oracle. /// @dev The local data parts are loaded into the preimage oracle under the context /// of the caller - no other account can write to the caller's context /// specific data. /// /// There are 5 local data identifiers: /// ┌────────────┬────────────────────────┐ /// │ Identifier │ Data │ /// ├────────────┼────────────────────────┤ /// │ 1 │ L1 Head Hash (bytes32) │ /// │ 2 │ Output Root (bytes32) │ /// │ 3 │ Root Claim (bytes32) │ /// │ 4 │ L2 Block Number (u64) │ /// │ 5 │ Chain ID (u64) │ /// └────────────┴────────────────────────┘ function loadLocalData( uint256 _ident, bytes32 _localContext, bytes32 _word, uint256 _size, uint256 _partOffset ) external returns (bytes32 key_); /// @notice Prepares a preimage to be read by keccak256 key, starting at the given offset and up to 32 bytes /// (clipped at preimage length, if out of data). /// @param _partOffset The offset of the preimage to read. /// @param _preimage The preimage data. function loadKeccak256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external; /// @notice Prepares a preimage to be read by sha256 key, starting at the given offset and up to 32 bytes /// (clipped at preimage length, if out of data). /// @param _partOffset The offset of the preimage to read. /// @param _preimage The preimage data. function loadSha256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; /// @title PreimageKeyLib /// @notice Shared utilities for localizing local keys in the preimage oracle. library PreimageKeyLib { /// @notice Generates a context-specific local key for the given local data identifier. /// @dev See `localize` for a description of the localization operation. /// @param _ident The identifier of the local data. [0, 32) bytes in size. /// @param _localContext The local context for the key. /// @return key_ The context-specific local key. function localizeIdent(uint256 _ident, bytes32 _localContext) internal view returns (bytes32 key_) { assembly { // Set the type byte in the given identifier to `1` (Local). We only care about // the [1, 32) bytes in this value. key_ := or(shl(248, 1), and(_ident, not(shl(248, 0xFF)))) } // Localize the key with the given local context. key_ = localize(key_, _localContext); } /// @notice Localizes a given local data key for the caller's context. /// @dev The localization operation is defined as: /// localize(k) = H(k .. sender .. local_context) & ~(0xFF << 248) | (0x01 << 248) /// where H is the Keccak-256 hash function. /// @param _key The local data key to localize. /// @param _localContext The local context for the key. /// @return localizedKey_ The localized local data key. function localize(bytes32 _key, bytes32 _localContext) internal view returns (bytes32 localizedKey_) { assembly { // Grab the current free memory pointer to restore later. let ptr := mload(0x40) // Store the local data key and caller next to each other in memory for hashing. mstore(0, _key) mstore(0x20, caller()) mstore(0x40, _localContext) // Localize the key with the above `localize` operation. localizedKey_ := or(and(keccak256(0, 0x60), not(shl(248, 0xFF))), shl(248, 1)) // Restore the free memory pointer. mstore(0x40, ptr) } } /// @notice Computes and returns the key for a global keccak pre-image. /// @param _preimage The pre-image. /// @return key_ The pre-image key. function keccak256PreimageKey(bytes memory _preimage) internal pure returns (bytes32 key_) { assembly { // Grab the size of the `_preimage` let size := mload(_preimage) // Compute the pre-image keccak256 hash (aka the pre-image key) let h := keccak256(add(_preimage, 0x20), size) // Mask out prefix byte, replace with type 2 byte key_ := or(and(h, not(shl(248, 0xFF))), shl(248, 2)) } } }
{ "remappings": [ "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@rari-capital/solmate/=lib/solmate/", "@cwia/=lib/clones-with-immutable-args/src/", "@lib-keccak/=lib/lib-keccak/contracts/lib/", "forge-std/=lib/forge-std/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "safe-contracts/=lib/safe-contracts/contracts/", "kontrol-cheatcodes/=lib/kontrol-cheatcodes/src/", "solady/=lib/solady/src/", "@eth-optimism/=node_modules/@eth-optimism/", "clones-with-immutable-args/=lib/clones-with-immutable-args/src/", "lib-keccak/=lib/lib-keccak/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 999999 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
[{"inputs":[{"internalType":"contract IPreimageOracle","name":"_oracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BRK_START","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IPreimageOracle","name":"oracle_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_stateData","type":"bytes"},{"internalType":"bytes","name":"_proof","type":"bytes"},{"internalType":"bytes32","name":"_localContext","type":"bytes32"}],"name":"step","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a060405234801561001057600080fd5b50604051611ec2380380611ec283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051611e3161009160003960008181608501526115ef0152611e316000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063155633fe146100465780637dc0d1d01461006b578063e14ced32146100af575b600080fd5b610051634000000081565b60405163ffffffff90911681526020015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610062565b6100c26100bd366004611d2e565b6100d0565b604051908152602001610062565b60006100da611c5b565b608081146100e757600080fd5b604051610600146100f757600080fd5b6084871461010457600080fd5b6101a4851461011257600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b60208110156101bd57823560e01c8252600490920191602090910190600101610199565b505050806101200151156101db576101d361061b565b915050610612565b6101408101805160010167ffffffffffffffff16905260608101516000906102039082610737565b9050603f601a82901c16600281148061022257508063ffffffff166003145b156102775760006002836303ffffff1663ffffffff16901b846080015163f00000001617905061026c8263ffffffff1660021461026057601f610263565b60005b60ff16826107f3565b945050505050610612565b6101608301516000908190601f601086901c81169190601587901c16602081106102a3576102a3611da2565b602002015192508063ffffffff851615806102c457508463ffffffff16601c145b156102fb578661016001518263ffffffff16602081106102e6576102e6611da2565b6020020151925050601f600b86901c166103b7565b60208563ffffffff16101561035d578463ffffffff16600c148061032557508463ffffffff16600d145b8061033657508463ffffffff16600e145b15610347578561ffff1692506103b7565b6103568661ffff1660106108e4565b92506103b7565b60288563ffffffff1610158061037957508463ffffffff166022145b8061038a57508463ffffffff166026145b156103b7578661016001518263ffffffff16602081106103ac576103ac611da2565b602002015192508190505b60048563ffffffff16101580156103d4575060088563ffffffff16105b806103e557508463ffffffff166001145b15610404576103f685878487610957565b975050505050505050610612565b63ffffffff6000602087831610610469576104248861ffff1660106108e4565b9095019463fffffffc861661043a816001610737565b915060288863ffffffff161015801561045a57508763ffffffff16603014155b1561046757809250600093505b505b600061047789888885610b67565b63ffffffff9081169150603f8a1690891615801561049c575060088163ffffffff1610155b80156104ae5750601c8163ffffffff16105b1561058b578063ffffffff16600814806104ce57508063ffffffff166009145b15610505576104f38163ffffffff166008146104ea57856104ed565b60005b896107f3565b9b505050505050505050505050610612565b8063ffffffff16600a03610525576104f3858963ffffffff8a16156112f7565b8063ffffffff16600b03610546576104f3858963ffffffff8a1615156112f7565b8063ffffffff16600c0361055d576104f38d6113dd565b60108163ffffffff161015801561057a5750601c8163ffffffff16105b1561058b576104f381898988611914565b8863ffffffff1660381480156105a6575063ffffffff861615155b156105db5760018b61016001518763ffffffff16602081106105ca576105ca611da2565b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff146105f8576105f884600184611b0e565b610604858360016112f7565b9b5050505050505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b60208110156106ba57601c8601518452602090950194600490930192600101610696565b506000835283830384a06000945080600181146106da5760039550610702565b8280156106f257600181146106fb5760029650610700565b60009650610700565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008061074383611bb2565b9050600384161561075357600080fd5b6020810190358460051c8160005b601b8110156107b95760208501943583821c6001168015610789576001811461079e576107af565b600084815260208390526040902093506107af565b600082815260208590526040902093505b5050600101610761565b5060805191508181146107d457630badf00d60005260206000fd5b5050601f94909416601c0360031b9390931c63ffffffff169392505050565b60006107fd611c5b565b60809050806060015160040163ffffffff16816080015163ffffffff1614610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b60608101805160808301805163ffffffff9081169093528583169052908516156108dc57806008018261016001518663ffffffff16602081106108cb576108cb611da2565b63ffffffff90921660209290920201525b61061261061b565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610941576000610943565b815b90861663ffffffff16179250505092915050565b6000610961611c5b565b608090506000816060015160040163ffffffff16826080015163ffffffff16146109e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f74000000000000000000000000604482015260640161087d565b8663ffffffff1660041480610a0257508663ffffffff166005145b15610a7e5760008261016001518663ffffffff1660208110610a2657610a26611da2565b602002015190508063ffffffff168563ffffffff16148015610a4e57508763ffffffff166004145b80610a7657508063ffffffff168563ffffffff1614158015610a7657508763ffffffff166005145b915050610afb565b8663ffffffff16600603610a9b5760008460030b13159050610afb565b8663ffffffff16600703610ab75760008460030b139050610afb565b8663ffffffff16600103610afb57601f601087901c166000819003610ae05760008560030b1291505b8063ffffffff16600103610af95760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b41576002610b268861ffff1660106108e4565b63ffffffff90811690911b8201600401166080840152610b53565b60808301805160040163ffffffff1690525b610b5b61061b565b98975050505050505050565b6000603f601a86901c16801580610b96575060088163ffffffff1610158015610b965750600f8163ffffffff16105b15610fec57603f86168160088114610bdd5760098114610be657600a8114610bef57600b8114610bf857600c8114610c0157600d8114610c0a57600e8114610c1357610c18565b60209150610c18565b60219150610c18565b602a9150610c18565b602b9150610c18565b60249150610c18565b60259150610c18565b602691505b508063ffffffff16600003610c3f5750505063ffffffff8216601f600686901c161b6112ef565b8063ffffffff16600203610c655750505063ffffffff8216601f600686901c161c6112ef565b8063ffffffff16600303610c9b57601f600688901c16610c9163ffffffff8716821c60208390036108e4565b93505050506112ef565b8063ffffffff16600403610cbd5750505063ffffffff8216601f84161b6112ef565b8063ffffffff16600603610cdf5750505063ffffffff8216601f84161c6112ef565b8063ffffffff16600703610d1257610d098663ffffffff168663ffffffff16901c876020036108e4565b925050506112ef565b8063ffffffff16600803610d2a5785925050506112ef565b8063ffffffff16600903610d425785925050506112ef565b8063ffffffff16600a03610d5a5785925050506112ef565b8063ffffffff16600b03610d725785925050506112ef565b8063ffffffff16600c03610d8a5785925050506112ef565b8063ffffffff16600f03610da25785925050506112ef565b8063ffffffff16601003610dba5785925050506112ef565b8063ffffffff16601103610dd25785925050506112ef565b8063ffffffff16601203610dea5785925050506112ef565b8063ffffffff16601303610e025785925050506112ef565b8063ffffffff16601803610e1a5785925050506112ef565b8063ffffffff16601903610e325785925050506112ef565b8063ffffffff16601a03610e4a5785925050506112ef565b8063ffffffff16601b03610e625785925050506112ef565b8063ffffffff16602003610e7b575050508282016112ef565b8063ffffffff16602103610e94575050508282016112ef565b8063ffffffff16602203610ead575050508183036112ef565b8063ffffffff16602303610ec6575050508183036112ef565b8063ffffffff16602403610edf575050508282166112ef565b8063ffffffff16602503610ef8575050508282176112ef565b8063ffffffff16602603610f11575050508282186112ef565b8063ffffffff16602703610f2b57505050828217196112ef565b8063ffffffff16602a03610f5c578460030b8660030b12610f4d576000610f50565b60015b60ff16925050506112ef565b8063ffffffff16602b03610f84578463ffffffff168663ffffffff1610610f4d576000610f50565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015260640161087d565b50610f84565b8063ffffffff16601c0361107057603f86166002819003611012575050508282026112ef565b8063ffffffff166020148061102d57508063ffffffff166021145b15610fe6578063ffffffff16602003611044579419945b60005b6380000000871615611066576401fffffffe600197881b169601611047565b92506112ef915050565b8063ffffffff16600f0361109257505065ffffffff0000601083901b166112ef565b8063ffffffff166020036110ce576110c68560031660080260180363ffffffff168463ffffffff16901c60ff1660086108e4565b9150506112ef565b8063ffffffff16602103611103576110c68560021660080260100363ffffffff168463ffffffff16901c61ffff1660106108e4565b8063ffffffff1660220361113257505063ffffffff60086003851602811681811b198416918316901b176112ef565b8063ffffffff1660230361114957829150506112ef565b8063ffffffff1660240361117b578460031660080260180363ffffffff168363ffffffff16901c60ff169150506112ef565b8063ffffffff166025036111ae578460021660080260100363ffffffff168363ffffffff16901c61ffff169150506112ef565b8063ffffffff166026036111e057505063ffffffff60086003851602601803811681811c198416918316901c176112ef565b8063ffffffff1660280361121657505060ff63ffffffff60086003861602601803811682811b9091188316918416901b176112ef565b8063ffffffff1660290361124d57505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b176112ef565b8063ffffffff16602a0361127c57505063ffffffff60086003851602811681811c198316918416901c176112ef565b8063ffffffff16602b0361129357839150506112ef565b8063ffffffff16602e036112c557505063ffffffff60086003851602601803811681811b198316918416901b176112ef565b8063ffffffff166030036112dc57829150506112ef565b8063ffffffff16603803610f8457839150505b949350505050565b6000611301611c5b565b506080602063ffffffff861610611374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015260640161087d565b63ffffffff8516158015906113865750825b156113ba57838161016001518663ffffffff16602081106113a9576113a9611da2565b63ffffffff90921660209290920201525b60808101805163ffffffff8082166060850152600490910116905261061261061b565b60006113e7611c5b565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa036114615781610fff81161561143057610fff811661100003015b8363ffffffff166000036114575760e08801805163ffffffff83820116909152955061145b565b8395505b506118d3565b8563ffffffff16610fcd0361147c57634000000094506118d3565b8563ffffffff166110180361149457600194506118d3565b8563ffffffff16611096036114ca57600161012088015260ff83166101008801526114bd61061b565b9998505050505050505050565b8563ffffffff16610fa3036117365763ffffffff8316156118d3577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8416016116f05760006115258363fffffffc166001610737565b60208901519091508060001a60010361159457604080516000838152336020528d83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790505b6040808a015190517fe03110e10000000000000000000000000000000000000000000000000000000081526004810183905263ffffffff9091166024820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e03110e1906044016040805180830381865afa158015611635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116599190611dd1565b91509150600386168060040382811015611671578092505b508186101561167e578591505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b039150811981169050838119871617955050506116d58663fffffffc16600186611b0e565b60408b018051820163ffffffff169052975061173192505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff841601611725578094506118d3565b63ffffffff9450600993505b6118d3565b8563ffffffff16610fa4036118275763ffffffff831660011480611760575063ffffffff83166002145b80611771575063ffffffff83166004145b1561177e578094506118d3565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8416016117255760006117be8363fffffffc166001610737565b602089015190915060038416600403838110156117d9578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b176020880152600060408801529350836118d3565b8563ffffffff16610fd7036118d3578163ffffffff166003036118c75763ffffffff8316158061185d575063ffffffff83166005145b8061186e575063ffffffff83166003145b1561187c57600094506118d3565b63ffffffff831660011480611897575063ffffffff83166002145b806118a8575063ffffffff83166006145b806118b9575063ffffffff83166004145b1561172557600194506118d3565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b015260040190911690526114bd61061b565b600061191e611c5b565b506080600063ffffffff871660100361193c575060c0810151611aa5565b8663ffffffff1660110361195b5763ffffffff861660c0830152611aa5565b8663ffffffff16601203611974575060a0810151611aa5565b8663ffffffff166013036119935763ffffffff861660a0830152611aa5565b8663ffffffff166018036119c75763ffffffff600387810b9087900b02602081901c821660c08501521660a0830152611aa5565b8663ffffffff166019036119f85763ffffffff86811681871602602081901c821660c08501521660a0830152611aa5565b8663ffffffff16601a03611a4e578460030b8660030b81611a1b57611a1b611df5565b0763ffffffff1660c0830152600385810b9087900b81611a3d57611a3d611df5565b0563ffffffff1660a0830152611aa5565b8663ffffffff16601b03611aa5578463ffffffff168663ffffffff1681611a7757611a77611df5565b0663ffffffff90811660c084015285811690871681611a9857611a98611df5565b0463ffffffff1660a08301525b63ffffffff841615611ae057808261016001518563ffffffff1660208110611acf57611acf611da2565b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611b0361061b565b979650505050505050565b6000611b1983611bb2565b90506003841615611b2957600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611ba75760208401933582821c6001168015611b775760018114611b8c57611b9d565b60008581526020839052604090209450611b9d565b600082815260208690526040902094505b5050600101611b4f565b505060805250505050565b60ff8116610380026101a4810190369061052401811015611c55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f6174610000000000000000000000000000000000000000000000000000000000606482015260840161087d565b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611cc1611cc6565b905290565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112611cf757600080fd5b50813567ffffffffffffffff811115611d0f57600080fd5b602083019150836020828501011115611d2757600080fd5b9250929050565b600080600080600060608688031215611d4657600080fd5b853567ffffffffffffffff80821115611d5e57600080fd5b611d6a89838a01611ce5565b90975095506020880135915080821115611d8357600080fd5b50611d9088828901611ce5565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060408385031215611de457600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a00000000000000000000000004ee7a915241a357e01c3320b764a96c6b84a7ae
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063155633fe146100465780637dc0d1d01461006b578063e14ced32146100af575b600080fd5b610051634000000081565b60405163ffffffff90911681526020015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000004ee7a915241a357e01c3320b764a96c6b84a7ae168152602001610062565b6100c26100bd366004611d2e565b6100d0565b604051908152602001610062565b60006100da611c5b565b608081146100e757600080fd5b604051610600146100f757600080fd5b6084871461010457600080fd5b6101a4851461011257600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b60208110156101bd57823560e01c8252600490920191602090910190600101610199565b505050806101200151156101db576101d361061b565b915050610612565b6101408101805160010167ffffffffffffffff16905260608101516000906102039082610737565b9050603f601a82901c16600281148061022257508063ffffffff166003145b156102775760006002836303ffffff1663ffffffff16901b846080015163f00000001617905061026c8263ffffffff1660021461026057601f610263565b60005b60ff16826107f3565b945050505050610612565b6101608301516000908190601f601086901c81169190601587901c16602081106102a3576102a3611da2565b602002015192508063ffffffff851615806102c457508463ffffffff16601c145b156102fb578661016001518263ffffffff16602081106102e6576102e6611da2565b6020020151925050601f600b86901c166103b7565b60208563ffffffff16101561035d578463ffffffff16600c148061032557508463ffffffff16600d145b8061033657508463ffffffff16600e145b15610347578561ffff1692506103b7565b6103568661ffff1660106108e4565b92506103b7565b60288563ffffffff1610158061037957508463ffffffff166022145b8061038a57508463ffffffff166026145b156103b7578661016001518263ffffffff16602081106103ac576103ac611da2565b602002015192508190505b60048563ffffffff16101580156103d4575060088563ffffffff16105b806103e557508463ffffffff166001145b15610404576103f685878487610957565b975050505050505050610612565b63ffffffff6000602087831610610469576104248861ffff1660106108e4565b9095019463fffffffc861661043a816001610737565b915060288863ffffffff161015801561045a57508763ffffffff16603014155b1561046757809250600093505b505b600061047789888885610b67565b63ffffffff9081169150603f8a1690891615801561049c575060088163ffffffff1610155b80156104ae5750601c8163ffffffff16105b1561058b578063ffffffff16600814806104ce57508063ffffffff166009145b15610505576104f38163ffffffff166008146104ea57856104ed565b60005b896107f3565b9b505050505050505050505050610612565b8063ffffffff16600a03610525576104f3858963ffffffff8a16156112f7565b8063ffffffff16600b03610546576104f3858963ffffffff8a1615156112f7565b8063ffffffff16600c0361055d576104f38d6113dd565b60108163ffffffff161015801561057a5750601c8163ffffffff16105b1561058b576104f381898988611914565b8863ffffffff1660381480156105a6575063ffffffff861615155b156105db5760018b61016001518763ffffffff16602081106105ca576105ca611da2565b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff146105f8576105f884600184611b0e565b610604858360016112f7565b9b5050505050505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b60208110156106ba57601c8601518452602090950194600490930192600101610696565b506000835283830384a06000945080600181146106da5760039550610702565b8280156106f257600181146106fb5760029650610700565b60009650610700565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008061074383611bb2565b9050600384161561075357600080fd5b6020810190358460051c8160005b601b8110156107b95760208501943583821c6001168015610789576001811461079e576107af565b600084815260208390526040902093506107af565b600082815260208590526040902093505b5050600101610761565b5060805191508181146107d457630badf00d60005260206000fd5b5050601f94909416601c0360031b9390931c63ffffffff169392505050565b60006107fd611c5b565b60809050806060015160040163ffffffff16816080015163ffffffff1614610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b60608101805160808301805163ffffffff9081169093528583169052908516156108dc57806008018261016001518663ffffffff16602081106108cb576108cb611da2565b63ffffffff90921660209290920201525b61061261061b565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610941576000610943565b815b90861663ffffffff16179250505092915050565b6000610961611c5b565b608090506000816060015160040163ffffffff16826080015163ffffffff16146109e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f74000000000000000000000000604482015260640161087d565b8663ffffffff1660041480610a0257508663ffffffff166005145b15610a7e5760008261016001518663ffffffff1660208110610a2657610a26611da2565b602002015190508063ffffffff168563ffffffff16148015610a4e57508763ffffffff166004145b80610a7657508063ffffffff168563ffffffff1614158015610a7657508763ffffffff166005145b915050610afb565b8663ffffffff16600603610a9b5760008460030b13159050610afb565b8663ffffffff16600703610ab75760008460030b139050610afb565b8663ffffffff16600103610afb57601f601087901c166000819003610ae05760008560030b1291505b8063ffffffff16600103610af95760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b41576002610b268861ffff1660106108e4565b63ffffffff90811690911b8201600401166080840152610b53565b60808301805160040163ffffffff1690525b610b5b61061b565b98975050505050505050565b6000603f601a86901c16801580610b96575060088163ffffffff1610158015610b965750600f8163ffffffff16105b15610fec57603f86168160088114610bdd5760098114610be657600a8114610bef57600b8114610bf857600c8114610c0157600d8114610c0a57600e8114610c1357610c18565b60209150610c18565b60219150610c18565b602a9150610c18565b602b9150610c18565b60249150610c18565b60259150610c18565b602691505b508063ffffffff16600003610c3f5750505063ffffffff8216601f600686901c161b6112ef565b8063ffffffff16600203610c655750505063ffffffff8216601f600686901c161c6112ef565b8063ffffffff16600303610c9b57601f600688901c16610c9163ffffffff8716821c60208390036108e4565b93505050506112ef565b8063ffffffff16600403610cbd5750505063ffffffff8216601f84161b6112ef565b8063ffffffff16600603610cdf5750505063ffffffff8216601f84161c6112ef565b8063ffffffff16600703610d1257610d098663ffffffff168663ffffffff16901c876020036108e4565b925050506112ef565b8063ffffffff16600803610d2a5785925050506112ef565b8063ffffffff16600903610d425785925050506112ef565b8063ffffffff16600a03610d5a5785925050506112ef565b8063ffffffff16600b03610d725785925050506112ef565b8063ffffffff16600c03610d8a5785925050506112ef565b8063ffffffff16600f03610da25785925050506112ef565b8063ffffffff16601003610dba5785925050506112ef565b8063ffffffff16601103610dd25785925050506112ef565b8063ffffffff16601203610dea5785925050506112ef565b8063ffffffff16601303610e025785925050506112ef565b8063ffffffff16601803610e1a5785925050506112ef565b8063ffffffff16601903610e325785925050506112ef565b8063ffffffff16601a03610e4a5785925050506112ef565b8063ffffffff16601b03610e625785925050506112ef565b8063ffffffff16602003610e7b575050508282016112ef565b8063ffffffff16602103610e94575050508282016112ef565b8063ffffffff16602203610ead575050508183036112ef565b8063ffffffff16602303610ec6575050508183036112ef565b8063ffffffff16602403610edf575050508282166112ef565b8063ffffffff16602503610ef8575050508282176112ef565b8063ffffffff16602603610f11575050508282186112ef565b8063ffffffff16602703610f2b57505050828217196112ef565b8063ffffffff16602a03610f5c578460030b8660030b12610f4d576000610f50565b60015b60ff16925050506112ef565b8063ffffffff16602b03610f84578463ffffffff168663ffffffff1610610f4d576000610f50565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015260640161087d565b50610f84565b8063ffffffff16601c0361107057603f86166002819003611012575050508282026112ef565b8063ffffffff166020148061102d57508063ffffffff166021145b15610fe6578063ffffffff16602003611044579419945b60005b6380000000871615611066576401fffffffe600197881b169601611047565b92506112ef915050565b8063ffffffff16600f0361109257505065ffffffff0000601083901b166112ef565b8063ffffffff166020036110ce576110c68560031660080260180363ffffffff168463ffffffff16901c60ff1660086108e4565b9150506112ef565b8063ffffffff16602103611103576110c68560021660080260100363ffffffff168463ffffffff16901c61ffff1660106108e4565b8063ffffffff1660220361113257505063ffffffff60086003851602811681811b198416918316901b176112ef565b8063ffffffff1660230361114957829150506112ef565b8063ffffffff1660240361117b578460031660080260180363ffffffff168363ffffffff16901c60ff169150506112ef565b8063ffffffff166025036111ae578460021660080260100363ffffffff168363ffffffff16901c61ffff169150506112ef565b8063ffffffff166026036111e057505063ffffffff60086003851602601803811681811c198416918316901c176112ef565b8063ffffffff1660280361121657505060ff63ffffffff60086003861602601803811682811b9091188316918416901b176112ef565b8063ffffffff1660290361124d57505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b176112ef565b8063ffffffff16602a0361127c57505063ffffffff60086003851602811681811c198316918416901c176112ef565b8063ffffffff16602b0361129357839150506112ef565b8063ffffffff16602e036112c557505063ffffffff60086003851602601803811681811b198316918416901b176112ef565b8063ffffffff166030036112dc57829150506112ef565b8063ffffffff16603803610f8457839150505b949350505050565b6000611301611c5b565b506080602063ffffffff861610611374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015260640161087d565b63ffffffff8516158015906113865750825b156113ba57838161016001518663ffffffff16602081106113a9576113a9611da2565b63ffffffff90921660209290920201525b60808101805163ffffffff8082166060850152600490910116905261061261061b565b60006113e7611c5b565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa036114615781610fff81161561143057610fff811661100003015b8363ffffffff166000036114575760e08801805163ffffffff83820116909152955061145b565b8395505b506118d3565b8563ffffffff16610fcd0361147c57634000000094506118d3565b8563ffffffff166110180361149457600194506118d3565b8563ffffffff16611096036114ca57600161012088015260ff83166101008801526114bd61061b565b9998505050505050505050565b8563ffffffff16610fa3036117365763ffffffff8316156118d3577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8416016116f05760006115258363fffffffc166001610737565b60208901519091508060001a60010361159457604080516000838152336020528d83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790505b6040808a015190517fe03110e10000000000000000000000000000000000000000000000000000000081526004810183905263ffffffff9091166024820152600090819073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000004ee7a915241a357e01c3320b764a96c6b84a7ae169063e03110e1906044016040805180830381865afa158015611635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116599190611dd1565b91509150600386168060040382811015611671578092505b508186101561167e578591505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b039150811981169050838119871617955050506116d58663fffffffc16600186611b0e565b60408b018051820163ffffffff169052975061173192505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff841601611725578094506118d3565b63ffffffff9450600993505b6118d3565b8563ffffffff16610fa4036118275763ffffffff831660011480611760575063ffffffff83166002145b80611771575063ffffffff83166004145b1561177e578094506118d3565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8416016117255760006117be8363fffffffc166001610737565b602089015190915060038416600403838110156117d9578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b176020880152600060408801529350836118d3565b8563ffffffff16610fd7036118d3578163ffffffff166003036118c75763ffffffff8316158061185d575063ffffffff83166005145b8061186e575063ffffffff83166003145b1561187c57600094506118d3565b63ffffffff831660011480611897575063ffffffff83166002145b806118a8575063ffffffff83166006145b806118b9575063ffffffff83166004145b1561172557600194506118d3565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b015260040190911690526114bd61061b565b600061191e611c5b565b506080600063ffffffff871660100361193c575060c0810151611aa5565b8663ffffffff1660110361195b5763ffffffff861660c0830152611aa5565b8663ffffffff16601203611974575060a0810151611aa5565b8663ffffffff166013036119935763ffffffff861660a0830152611aa5565b8663ffffffff166018036119c75763ffffffff600387810b9087900b02602081901c821660c08501521660a0830152611aa5565b8663ffffffff166019036119f85763ffffffff86811681871602602081901c821660c08501521660a0830152611aa5565b8663ffffffff16601a03611a4e578460030b8660030b81611a1b57611a1b611df5565b0763ffffffff1660c0830152600385810b9087900b81611a3d57611a3d611df5565b0563ffffffff1660a0830152611aa5565b8663ffffffff16601b03611aa5578463ffffffff168663ffffffff1681611a7757611a77611df5565b0663ffffffff90811660c084015285811690871681611a9857611a98611df5565b0463ffffffff1660a08301525b63ffffffff841615611ae057808261016001518563ffffffff1660208110611acf57611acf611da2565b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611b0361061b565b979650505050505050565b6000611b1983611bb2565b90506003841615611b2957600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611ba75760208401933582821c6001168015611b775760018114611b8c57611b9d565b60008581526020839052604090209450611b9d565b600082815260208690526040902094505b5050600101611b4f565b505060805250505050565b60ff8116610380026101a4810190369061052401811015611c55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f6174610000000000000000000000000000000000000000000000000000000000606482015260840161087d565b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611cc1611cc6565b905290565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112611cf757600080fd5b50813567ffffffffffffffff811115611d0f57600080fd5b602083019150836020828501011115611d2757600080fd5b9250929050565b600080600080600060608688031215611d4657600080fd5b853567ffffffffffffffff80821115611d5e57600080fd5b611d6a89838a01611ce5565b90975095506020880135915080821115611d8357600080fd5b50611d9088828901611ce5565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060408385031215611de457600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000004ee7a915241a357e01c3320b764a96c6b84a7ae
-----Decoded View---------------
Arg [0] : _oracle (address): 0x04eE7A915241A357e01c3320b764a96c6b84A7Ae
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000004ee7a915241a357e01c3320b764a96c6b84a7ae
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.