-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Opcode types for Ethereum Virtual Machine (EVM) -- -- This library provides opcode types for the Ethereum Virtual Machine. @package evm-opcodes @version 0.1.2 -- | This module exposes the Opcode' abstract type. module EVM.Opcode.Internal -- | An Opcode' is an Ethereum VM Opcode with parameterised jumps. -- -- For a plain opcode using the basic EVM stack-based jumps, use -- Opcode instead. -- -- This type is used for defining and translating from annotated opcodes, -- e.g. with labelled jumps. data Opcode' j -- | 0x00 STOP :: Opcode' j -- | 0x01 ADD :: Opcode' j -- | 0x02 MUL :: Opcode' j -- | 0x03 SUB :: Opcode' j -- | 0x04 DIV :: Opcode' j -- | 0x05 SDIV :: Opcode' j -- | 0x06 MOD :: Opcode' j -- | 0x07 SMOD :: Opcode' j -- | 0x08 ADDMOD :: Opcode' j -- | 0x09 MULMOD :: Opcode' j -- | 0x0a EXP :: Opcode' j -- | 0x0b SIGNEXTEND :: Opcode' j -- | 0x10 LT :: Opcode' j -- | 0x11 GT :: Opcode' j -- | 0x12 SLT :: Opcode' j -- | 0x13 SGT :: Opcode' j -- | 0x14 EQ :: Opcode' j -- | 0x15 ISZERO :: Opcode' j -- | 0x16 AND :: Opcode' j -- | 0x17 OR :: Opcode' j -- | 0x18 XOR :: Opcode' j -- | 0x19 NOT :: Opcode' j -- | 0x1a BYTE :: Opcode' j -- | 0x1b, https://eips.ethereum.org/EIPS/eip-145 SHL :: Opcode' j -- | 0x1c, https://eips.ethereum.org/EIPS/eip-145 SHR :: Opcode' j -- | 0x1d, https://eips.ethereum.org/EIPS/eip-145 SAR :: Opcode' j -- | 0x20 SHA3 :: Opcode' j -- | 0x30 ADDRESS :: Opcode' j -- | 0x31 BALANCE :: Opcode' j -- | 0x32 ORIGIN :: Opcode' j -- | 0x33 CALLER :: Opcode' j -- | 0x34 CALLVALUE :: Opcode' j -- | 0x35 CALLDATALOAD :: Opcode' j -- | 0x36 CALLDATASIZE :: Opcode' j -- | 0x37 CALLDATACOPY :: Opcode' j -- | 0x38 CODESIZE :: Opcode' j -- | 0x39 CODECOPY :: Opcode' j -- | 0x3a GASPRICE :: Opcode' j -- | 0x3b EXTCODESIZE :: Opcode' j -- | 0x3c EXTCODECOPY :: Opcode' j -- | 0x3d, https://eips.ethereum.org/EIPS/eip-211 RETURNDATASIZE :: Opcode' j -- | 0x3e, https://eips.ethereum.org/EIPS/eip-211 RETURNDATACOPY :: Opcode' j -- | 0x3f, https://eips.ethereum.org/EIPS/eip-1052 EXTCODEHASH :: Opcode' j -- | 0x40 BLOCKHASH :: Opcode' j -- | 0x41 COINBASE :: Opcode' j -- | 0x42 TIMESTAMP :: Opcode' j -- | 0x43 NUMBER :: Opcode' j -- | 0x44 DIFFICULTY :: Opcode' j -- | 0x45 GASLIMIT :: Opcode' j -- | 0x46, https://eips.ethereum.org/EIPS/eip-1344 CHAINID :: Opcode' j -- | 0x47, https://eips.ethereum.org/EIPS/eip-1884 SELFBALANCE :: Opcode' j -- | 0x50 POP :: Opcode' j -- | 0x51 MLOAD :: Opcode' j -- | 0x52 MSTORE :: Opcode' j -- | 0x53 MSTORE8 :: Opcode' j -- | 0x54 SLOAD :: Opcode' j -- | 0x55 SSTORE :: Opcode' j -- | 0x56 JUMP :: j -> Opcode' j -- | 0x57 JUMPI :: j -> Opcode' j -- | 0x58 PC :: Opcode' j -- | 0x59 MSIZE :: Opcode' j -- | 0x5a GAS :: Opcode' j -- | 0x5b JUMPDEST :: j -> Opcode' j -- | 0x60 - 0x7f (PUSH1 - PUSH32) PUSH :: !Word256 -> Opcode' j -- | 0x80 - 0x8f (DUP1 - DUP16) DUP :: !Ord16 -> Opcode' j -- | 0x90 - 0x9f (SWAP1 - SWAP16) SWAP :: !Ord16 -> Opcode' j -- | 0xa0 - 0xa4 (LOG0 - LOG4) LOG :: !Ord5 -> Opcode' j -- | 0xf0 CREATE :: Opcode' j -- | 0xf1 CALL :: Opcode' j -- | 0xf2 CALLCODE :: Opcode' j -- | 0xf3 RETURN :: Opcode' j -- | 0xf4, https://eips.ethereum.org/EIPS/eip-7 DELEGATECALL :: Opcode' j -- | 0xf5, https://eips.ethereum.org/EIPS/eip-1014 CREATE2 :: Opcode' j -- | 0xfa STATICCALL :: Opcode' j -- | 0xfd, https://eips.ethereum.org/EIPS/eip-140 REVERT :: Opcode' j -- | 0xfe, https://eips.ethereum.org/EIPS/eip-141 INVALID :: Opcode' j -- | 0xff, https://eips.ethereum.org/EIPS/eip-6 SELFDESTRUCT :: Opcode' j -- | Convert any Opcode' a into an Opcode' -- (). concrete :: Opcode' a -> Opcode' () -- | Extract the a from a JUMP a or a -- JUMPI a. jumpAnnot :: Opcode' a -> Maybe a -- | Extract the a from a JUMPDEST a. jumpdestAnnot :: Opcode' a -> Maybe a -- | Convert an Ord5 or an Ord16 to a Word8. toWord8 :: Enum e => e -> Word8 -- | Convert a Word8 to an Ord5 or an Ord16. fromWord8 :: Enum e => Word8 -> e -- | Convenience type of cardinality 5 for LOG. data Ord5 Ord5_0 :: Ord5 Ord5_1 :: Ord5 Ord5_2 :: Ord5 Ord5_3 :: Ord5 Ord5_4 :: Ord5 -- | Convenience type of cardinality 16 for DUP and SWAP. data Ord16 Ord16_1 :: Ord16 Ord16_2 :: Ord16 Ord16_3 :: Ord16 Ord16_4 :: Ord16 Ord16_5 :: Ord16 Ord16_6 :: Ord16 Ord16_7 :: Ord16 Ord16_8 :: Ord16 Ord16_9 :: Ord16 Ord16_10 :: Ord16 Ord16_11 :: Ord16 Ord16_12 :: Ord16 Ord16_13 :: Ord16 Ord16_14 :: Ord16 Ord16_15 :: Ord16 Ord16_16 :: Ord16 -- | An OpcodeSpec for a given Opcode contains the numeric -- encoding of the opcode, the number of items that this opcode removes -- from the stack (α), and the number of items added to the stack (δ). -- These values are documented in the Ethereum Yellow Paper. -- -- Examples of OpcodeSpecs: -- --
--   --         Hex  α δ
--   OpcodeSpec 0x01 2 1 "add"
--   OpcodeSpec 0x60 0 1 "push1 255"
--   OpcodeSpec 0x61 0 1 "push2 256"
--   
data OpcodeSpec OpcodeSpec :: !Word8 -> !Word8 -> !Word8 -> !Text -> OpcodeSpec -- | Numeric encoding of opcode [opcodeEncoding] :: OpcodeSpec -> !Word8 -- | Number of items opcode places on stack (α) [opcodeAlpha] :: OpcodeSpec -> !Word8 -- | Number of items opcode removes from stack (δ) [opcodeDelta] :: OpcodeSpec -> !Word8 -- | Printable name for opcode, e.g. "add" [opcodeName] :: OpcodeSpec -> !Text -- | Given an Opcode', produce its OpcodeSpec. -- -- For DUP, SWAP and LOG this depends on the -- specific variant, and for PUSH it depends on the size of the -- constant being pushed. opcodeSpec :: Opcode' j -> OpcodeSpec -- | Convert the constant argument of a PUSH to the opcode encoding -- (0x60--0x7f) and its constant split into Word8 segments. push' :: Word256 -> (Word8, [Word8]) -- | Use DUP1 instead of DUP Ord16_1. pattern DUP1 :: forall j. Opcode' j -- | Use DUP2 instead of DUP Ord16_2. pattern DUP2 :: forall j. Opcode' j -- | Use DUP3 instead of DUP Ord16_3. pattern DUP3 :: forall j. Opcode' j -- | Use DUP4 instead of DUP Ord16_4. pattern DUP4 :: forall j. Opcode' j -- | Use DUP5 instead of DUP Ord16_5. pattern DUP5 :: forall j. Opcode' j -- | Use DUP6 instead of DUP Ord16_6. pattern DUP6 :: forall j. Opcode' j -- | Use DUP7 instead of DUP Ord16_7. pattern DUP7 :: forall j. Opcode' j -- | Use DUP8 instead of DUP Ord16_8. pattern DUP8 :: forall j. Opcode' j -- | Use DUP9 instead of DUP Ord16_9. pattern DUP9 :: forall j. Opcode' j -- | Use DUP10 instead of DUP Ord16_10. pattern DUP10 :: forall j. Opcode' j -- | Use DUP11 instead of DUP Ord16_11. pattern DUP11 :: forall j. Opcode' j -- | Use DUP12 instead of DUP Ord16_12. pattern DUP12 :: forall j. Opcode' j -- | Use DUP13 instead of DUP Ord16_13. pattern DUP13 :: forall j. Opcode' j -- | Use DUP14 instead of DUP Ord16_14. pattern DUP14 :: forall j. Opcode' j -- | Use DUP15 instead of DUP Ord16_15. pattern DUP15 :: forall j. Opcode' j -- | Use DUP16 instead of DUP Ord16_16. pattern DUP16 :: forall j. Opcode' j -- | Use SWAP1 instead of SWAP Ord16_1, etc. pattern SWAP1 :: forall j. Opcode' j -- | Use SWAP2 instead of SWAP Ord16_2, etc. pattern SWAP2 :: forall j. Opcode' j -- | Use SWAP3 instead of SWAP Ord16_3, etc. pattern SWAP3 :: forall j. Opcode' j -- | Use SWAP4 instead of SWAP Ord16_4, etc. pattern SWAP4 :: forall j. Opcode' j -- | Use SWAP5 instead of SWAP Ord16_5, etc. pattern SWAP5 :: forall j. Opcode' j -- | Use SWAP6 instead of SWAP Ord16_6, etc. pattern SWAP6 :: forall j. Opcode' j -- | Use SWAP7 instead of SWAP Ord16_7, etc. pattern SWAP7 :: forall j. Opcode' j -- | Use SWAP8 instead of SWAP Ord16_8, etc. pattern SWAP8 :: forall j. Opcode' j -- | Use SWAP9 instead of SWAP Ord16_9, etc. pattern SWAP9 :: forall j. Opcode' j -- | Use SWAP10 instead of SWAP Ord16_10, -- etc. pattern SWAP10 :: forall j. Opcode' j -- | Use SWAP11 instead of SWAP Ord16_11, -- etc. pattern SWAP11 :: forall j. Opcode' j -- | Use SWAP12 instead of SWAP Ord16_12, -- etc. pattern SWAP12 :: forall j. Opcode' j -- | Use SWAP13 instead of SWAP Ord16_13, -- etc. pattern SWAP13 :: forall j. Opcode' j -- | Use SWAP14 instead of SWAP Ord16_14, -- etc. pattern SWAP14 :: forall j. Opcode' j -- | Use SWAP15 instead of SWAP Ord16_15, -- etc. pattern SWAP15 :: forall j. Opcode' j -- | Use SWAP16 instead of SWAP Ord16_16, -- etc. pattern SWAP16 :: forall j. Opcode' j -- | Use LOG0 instead of LOG Ord5_0. pattern LOG0 :: forall j. Opcode' j -- | Use LOG1 instead of LOG Ord5_1. pattern LOG1 :: forall j. Opcode' j -- | Use LOG2 instead of LOG Ord5_2. pattern LOG2 :: forall j. Opcode' j -- | Use LOG3 instead of LOG Ord5_3. pattern LOG3 :: forall j. Opcode' j -- | Use LOG4 instead of LOG Ord5_4. pattern LOG4 :: forall j. Opcode' j instance GHC.Enum.Bounded EVM.Opcode.Internal.Ord5 instance GHC.Enum.Enum EVM.Opcode.Internal.Ord5 instance GHC.Classes.Ord EVM.Opcode.Internal.Ord5 instance GHC.Classes.Eq EVM.Opcode.Internal.Ord5 instance GHC.Enum.Bounded EVM.Opcode.Internal.Ord16 instance GHC.Enum.Enum EVM.Opcode.Internal.Ord16 instance GHC.Classes.Ord EVM.Opcode.Internal.Ord16 instance GHC.Classes.Eq EVM.Opcode.Internal.Ord16 instance GHC.Base.Functor EVM.Opcode.Internal.Opcode' instance GHC.Classes.Ord j => GHC.Classes.Ord (EVM.Opcode.Internal.Opcode' j) instance GHC.Classes.Eq j => GHC.Classes.Eq (EVM.Opcode.Internal.Opcode' j) instance GHC.Show.Show EVM.Opcode.Internal.OpcodeSpec instance GHC.Classes.Eq EVM.Opcode.Internal.OpcodeSpec instance GHC.Show.Show a => GHC.Show.Show (EVM.Opcode.Internal.Opcode' a) -- | This module exposes the Opcode type for expressing Ethereum VM -- opcodes as extracted from the Ethereum Yellow Paper with amendments -- from various EIPs. The Yellow Paper is available at: -- -- https://ethereum.github.io/yellowpaper/paper.pdf -- -- The list of opcodes is found in appendix H.2. -- -- But it is not always up-to-date, so keeping track of EIPs that add or -- modify instructions is necessary. See comments in this module for the -- references to these additions. module EVM.Opcode -- | An Opcode is a plain, parameterless Ethereum VM Opcode. type Opcode = Opcode' () -- | An Opcode' is an Ethereum VM Opcode with parameterised jumps. -- -- For a plain opcode using the basic EVM stack-based jumps, use -- Opcode instead. -- -- This type is used for defining and translating from annotated opcodes, -- e.g. with labelled jumps. data Opcode' j -- | 0x00 STOP :: Opcode' j -- | 0x01 ADD :: Opcode' j -- | 0x02 MUL :: Opcode' j -- | 0x03 SUB :: Opcode' j -- | 0x04 DIV :: Opcode' j -- | 0x05 SDIV :: Opcode' j -- | 0x06 MOD :: Opcode' j -- | 0x07 SMOD :: Opcode' j -- | 0x08 ADDMOD :: Opcode' j -- | 0x09 MULMOD :: Opcode' j -- | 0x0a EXP :: Opcode' j -- | 0x0b SIGNEXTEND :: Opcode' j -- | 0x10 LT :: Opcode' j -- | 0x11 GT :: Opcode' j -- | 0x12 SLT :: Opcode' j -- | 0x13 SGT :: Opcode' j -- | 0x14 EQ :: Opcode' j -- | 0x15 ISZERO :: Opcode' j -- | 0x16 AND :: Opcode' j -- | 0x17 OR :: Opcode' j -- | 0x18 XOR :: Opcode' j -- | 0x19 NOT :: Opcode' j -- | 0x1a BYTE :: Opcode' j -- | 0x1b, https://eips.ethereum.org/EIPS/eip-145 SHL :: Opcode' j -- | 0x1c, https://eips.ethereum.org/EIPS/eip-145 SHR :: Opcode' j -- | 0x1d, https://eips.ethereum.org/EIPS/eip-145 SAR :: Opcode' j -- | 0x20 SHA3 :: Opcode' j -- | 0x30 ADDRESS :: Opcode' j -- | 0x31 BALANCE :: Opcode' j -- | 0x32 ORIGIN :: Opcode' j -- | 0x33 CALLER :: Opcode' j -- | 0x34 CALLVALUE :: Opcode' j -- | 0x35 CALLDATALOAD :: Opcode' j -- | 0x36 CALLDATASIZE :: Opcode' j -- | 0x37 CALLDATACOPY :: Opcode' j -- | 0x38 CODESIZE :: Opcode' j -- | 0x39 CODECOPY :: Opcode' j -- | 0x3a GASPRICE :: Opcode' j -- | 0x3b EXTCODESIZE :: Opcode' j -- | 0x3c EXTCODECOPY :: Opcode' j -- | 0x3d, https://eips.ethereum.org/EIPS/eip-211 RETURNDATASIZE :: Opcode' j -- | 0x3e, https://eips.ethereum.org/EIPS/eip-211 RETURNDATACOPY :: Opcode' j -- | 0x3f, https://eips.ethereum.org/EIPS/eip-1052 EXTCODEHASH :: Opcode' j -- | 0x40 BLOCKHASH :: Opcode' j -- | 0x41 COINBASE :: Opcode' j -- | 0x42 TIMESTAMP :: Opcode' j -- | 0x43 NUMBER :: Opcode' j -- | 0x44 DIFFICULTY :: Opcode' j -- | 0x45 GASLIMIT :: Opcode' j -- | 0x46, https://eips.ethereum.org/EIPS/eip-1344 CHAINID :: Opcode' j -- | 0x47, https://eips.ethereum.org/EIPS/eip-1884 SELFBALANCE :: Opcode' j -- | 0x50 POP :: Opcode' j -- | 0x51 MLOAD :: Opcode' j -- | 0x52 MSTORE :: Opcode' j -- | 0x53 MSTORE8 :: Opcode' j -- | 0x54 SLOAD :: Opcode' j -- | 0x55 SSTORE :: Opcode' j -- | 0x56 JUMP :: j -> Opcode' j -- | 0x57 JUMPI :: j -> Opcode' j -- | 0x58 PC :: Opcode' j -- | 0x59 MSIZE :: Opcode' j -- | 0x5a GAS :: Opcode' j -- | 0x5b JUMPDEST :: j -> Opcode' j -- | 0x60 - 0x7f (PUSH1 - PUSH32) PUSH :: !Word256 -> Opcode' j -- | 0x80 - 0x8f (DUP1 - DUP16) DUP :: !Ord16 -> Opcode' j -- | 0x90 - 0x9f (SWAP1 - SWAP16) SWAP :: !Ord16 -> Opcode' j -- | 0xa0 - 0xa4 (LOG0 - LOG4) LOG :: !Ord5 -> Opcode' j -- | 0xf0 CREATE :: Opcode' j -- | 0xf1 CALL :: Opcode' j -- | 0xf2 CALLCODE :: Opcode' j -- | 0xf3 RETURN :: Opcode' j -- | 0xf4, https://eips.ethereum.org/EIPS/eip-7 DELEGATECALL :: Opcode' j -- | 0xf5, https://eips.ethereum.org/EIPS/eip-1014 CREATE2 :: Opcode' j -- | 0xfa STATICCALL :: Opcode' j -- | 0xfd, https://eips.ethereum.org/EIPS/eip-140 REVERT :: Opcode' j -- | 0xfe, https://eips.ethereum.org/EIPS/eip-141 INVALID :: Opcode' j -- | 0xff, https://eips.ethereum.org/EIPS/eip-6 SELFDESTRUCT :: Opcode' j -- | An OpcodeSpec for a given Opcode contains the numeric -- encoding of the opcode, the number of items that this opcode removes -- from the stack (α), and the number of items added to the stack (δ). -- These values are documented in the Ethereum Yellow Paper. -- -- Examples of OpcodeSpecs: -- --
--   --         Hex  α δ
--   OpcodeSpec 0x01 2 1 "add"
--   OpcodeSpec 0x60 0 1 "push1 255"
--   OpcodeSpec 0x61 0 1 "push2 256"
--   
data OpcodeSpec OpcodeSpec :: !Word8 -> !Word8 -> !Word8 -> !Text -> OpcodeSpec -- | Numeric encoding of opcode [opcodeEncoding] :: OpcodeSpec -> !Word8 -- | Number of items opcode places on stack (α) [opcodeAlpha] :: OpcodeSpec -> !Word8 -- | Number of items opcode removes from stack (δ) [opcodeDelta] :: OpcodeSpec -> !Word8 -- | Printable name for opcode, e.g. "add" [opcodeName] :: OpcodeSpec -> !Text -- | Given an Opcode', produce its OpcodeSpec. -- -- For DUP, SWAP and LOG this depends on the -- specific variant, and for PUSH it depends on the size of the -- constant being pushed. opcodeSpec :: Opcode' j -> OpcodeSpec -- | jump is a plain parameterless Opcode. jump :: Opcode -- | jumpi is a plain parameterless Opcode. jumpi :: Opcode -- | jumpdest is a plain parameterless Opcode. jumpdest :: Opcode -- | Extract the a from a JUMP a or a -- JUMPI a. jumpAnnot :: Opcode' a -> Maybe a -- | Extract the a from a JUMPDEST a. jumpdestAnnot :: Opcode' a -> Maybe a -- | Convert any Opcode' a into an Opcode' -- (). concrete :: Opcode' a -> Opcode' () -- | Show Opcode as Text. opcodeText :: Opcode -> Text -- | Calculate the size in bytes of an encoded opcode. The only -- Opcode that uses more than one byte is PUSH. Sizes are -- trivially determined for only Opcode with unlabelled jumps, -- since we cannot know e.g. where the label of a LabelledOpcode -- points to before code generation has completed. opcodeSize :: Num i => Opcode -> i -- | Convert a [Opcode] to a string of ASCII hexadecimals. toHex :: IsString s => [Opcode] -> s -- | Convert a [Opcode] to bytecode. pack :: [Opcode] -> ByteString -- | Convert an Opcode to a [Word8]. -- -- To convert many Opcodes to bytecode, use pack. toBytes :: Opcode -> [Word8] -- | Determine if a byte represents a DUP opcode (DUP1 -- -- DUP16). isDUP :: Word8 -> Bool -- | Determine if a byte represents a SWAP opcode (SWAP1 -- -- SWAP16). isSWAP :: Word8 -> Bool -- | Determine if a byte represents a LOG opcode (LOG1 -- -- LOG4). isLOG :: Word8 -> Bool -- | Determine if a byte represents a PUSH opcode. isPUSH :: Word8 -> ByteString -> Bool -- | Read a DUP opcode (DUP1 -- DUP16) safely. readDUP :: Word8 -> Maybe Opcode -- | Read a SWAP opcode (SWAP1 -- SWAP16) safely. readSWAP :: Word8 -> Maybe Opcode -- | Read a LOG opcode (LOG1 -- LOG4) safely. readLOG :: Word8 -> Maybe Opcode -- | Read a PUSH opcode safely. readPUSH :: Word8 -> ByteString -> Maybe Opcode -- | Parse an Opcode from a Word8. In case of PUSH -- instructions, read the constant being pushed from a subsequent -- ByteString. readOp :: Word8 -> ByteString -> Maybe Opcode -- | Use DUP1 instead of DUP Ord16_1. pattern DUP1 :: forall j. Opcode' j -- | Use DUP2 instead of DUP Ord16_2. pattern DUP2 :: forall j. Opcode' j -- | Use DUP3 instead of DUP Ord16_3. pattern DUP3 :: forall j. Opcode' j -- | Use DUP4 instead of DUP Ord16_4. pattern DUP4 :: forall j. Opcode' j -- | Use DUP5 instead of DUP Ord16_5. pattern DUP5 :: forall j. Opcode' j -- | Use DUP6 instead of DUP Ord16_6. pattern DUP6 :: forall j. Opcode' j -- | Use DUP7 instead of DUP Ord16_7. pattern DUP7 :: forall j. Opcode' j -- | Use DUP8 instead of DUP Ord16_8. pattern DUP8 :: forall j. Opcode' j -- | Use DUP9 instead of DUP Ord16_9. pattern DUP9 :: forall j. Opcode' j -- | Use DUP10 instead of DUP Ord16_10. pattern DUP10 :: forall j. Opcode' j -- | Use DUP11 instead of DUP Ord16_11. pattern DUP11 :: forall j. Opcode' j -- | Use DUP12 instead of DUP Ord16_12. pattern DUP12 :: forall j. Opcode' j -- | Use DUP13 instead of DUP Ord16_13. pattern DUP13 :: forall j. Opcode' j -- | Use DUP14 instead of DUP Ord16_14. pattern DUP14 :: forall j. Opcode' j -- | Use DUP15 instead of DUP Ord16_15. pattern DUP15 :: forall j. Opcode' j -- | Use DUP16 instead of DUP Ord16_16. pattern DUP16 :: forall j. Opcode' j -- | Use SWAP1 instead of SWAP Ord16_1, etc. pattern SWAP1 :: forall j. Opcode' j -- | Use SWAP2 instead of SWAP Ord16_2, etc. pattern SWAP2 :: forall j. Opcode' j -- | Use SWAP3 instead of SWAP Ord16_3, etc. pattern SWAP3 :: forall j. Opcode' j -- | Use SWAP4 instead of SWAP Ord16_4, etc. pattern SWAP4 :: forall j. Opcode' j -- | Use SWAP5 instead of SWAP Ord16_5, etc. pattern SWAP5 :: forall j. Opcode' j -- | Use SWAP6 instead of SWAP Ord16_6, etc. pattern SWAP6 :: forall j. Opcode' j -- | Use SWAP7 instead of SWAP Ord16_7, etc. pattern SWAP7 :: forall j. Opcode' j -- | Use SWAP8 instead of SWAP Ord16_8, etc. pattern SWAP8 :: forall j. Opcode' j -- | Use SWAP9 instead of SWAP Ord16_9, etc. pattern SWAP9 :: forall j. Opcode' j -- | Use SWAP10 instead of SWAP Ord16_10, -- etc. pattern SWAP10 :: forall j. Opcode' j -- | Use SWAP11 instead of SWAP Ord16_11, -- etc. pattern SWAP11 :: forall j. Opcode' j -- | Use SWAP12 instead of SWAP Ord16_12, -- etc. pattern SWAP12 :: forall j. Opcode' j -- | Use SWAP13 instead of SWAP Ord16_13, -- etc. pattern SWAP13 :: forall j. Opcode' j -- | Use SWAP14 instead of SWAP Ord16_14, -- etc. pattern SWAP14 :: forall j. Opcode' j -- | Use SWAP15 instead of SWAP Ord16_15, -- etc. pattern SWAP15 :: forall j. Opcode' j -- | Use SWAP16 instead of SWAP Ord16_16, -- etc. pattern SWAP16 :: forall j. Opcode' j -- | Use LOG0 instead of LOG Ord5_0. pattern LOG0 :: forall j. Opcode' j -- | Use LOG1 instead of LOG Ord5_1. pattern LOG1 :: forall j. Opcode' j -- | Use LOG2 instead of LOG Ord5_2. pattern LOG2 :: forall j. Opcode' j -- | Use LOG3 instead of LOG Ord5_3. pattern LOG3 :: forall j. Opcode' j -- | Use LOG4 instead of LOG Ord5_4. pattern LOG4 :: forall j. Opcode' j -- | This module exposes the PositionalOpcode type for expressing -- Ethereum VM opcodes where jumps and jumpdests are annotated with the -- byte position of the translated opcode. -- -- This representation is useful for when generating code that refers to -- the size of itself or other chunks of code. E.g. the CODECOPY segment -- of an Ethereum contract must refer to the size of the code being -- copied, and determining the size of a jump is trivial when it's -- annotated with the destination address. module EVM.Opcode.Positional -- | The position of an Opcode. type Position = Word -- | A PositionalOpcode has byte positions annotated at JUMP, -- JUMPI and JUMPDEST; on JUMP and JUMPI the -- positions denote where they jump to, and on JUMPDEST they -- denote the position of the opcode itself. type PositionalOpcode = Opcode' Position -- | Translate a PositionalOpcode into an Opcode by -- converting the position into a PUSH instruction. translate :: [PositionalOpcode] -> [Opcode] -- | The size of a jump to some absolute position. jumpSize :: Num i => Position -> i -- | This module exposes a generic method of traversing Opcode's. module EVM.Opcode.Traversal -- | An OpcodeMapper is a collection of four mapping functions that -- can map any Opcode' a to an Opcode' b. -- For each of the three opcodes that are annotated, JUMP, -- JUMPI and JUMPDEST, a separate mapping function is -- specified, and for any other opcode, a general mapping function is -- specified that falls back to the same opcode of type -- Opcode' b. -- -- See translate for an example of usage. data OpcodeMapper m a b OpcodeMapper :: (a -> m (Opcode' b)) -> (a -> m (Opcode' b)) -> (a -> m (Opcode' b)) -> (Opcode' a -> m (Maybe (Opcode' b))) -> OpcodeMapper m a b [mapOnJump] :: OpcodeMapper m a b -> a -> m (Opcode' b) [mapOnJumpi] :: OpcodeMapper m a b -> a -> m (Opcode' b) [mapOnJumpdest] :: OpcodeMapper m a b -> a -> m (Opcode' b) [mapOnOther] :: OpcodeMapper m a b -> Opcode' a -> m (Maybe (Opcode' b)) -- | Given an OpcodeMapper and an Opcode' a, produce -- m (Opcode' b). mapOpcodeM :: forall m a b. Monad m => OpcodeMapper m a b -> Opcode' a -> m (Opcode' b) -- | This module exposes the LabelledOpcode type for expressing -- Ethereum VM opcodes with labelled jumps. Plain Ethereum VM Opcodes are -- not so ergonomic because one has to know the exact byte offset of the -- target JUMPDEST. -- -- With Opcode the byte offset is pushed to the stack via -- PUSH, but the offset to the JUMPDEST depends on all -- occurrences of PUSH prior to the label, including the -- PUSH to the label itself. module EVM.Opcode.Labelled -- | For now, all labels are Text. type Label = Text -- | LabelledOpcodes use Label to represent jumps. -- -- In particular, JUMP "name", JUMPI -- "name" and JUMPDEST "name". -- -- All other opcodes remain the same. type LabelledOpcode = Opcode' Label -- | Translation of LabelledOpcodes into PositionalOpcodes -- may fail if a jump is made to a non-occurring JUMPDEST or a -- JUMPDEST occurs twice. data TranslateError TranslateError :: [Label] -> [Label] -> TranslateError [translateErrorMissingJumpdests] :: TranslateError -> [Label] [translateErrorDuplicateJumpdests] :: TranslateError -> [Label] -- | Replace all labels with absolute positions. -- -- Positions are calculated by fixed-point iteration to account for -- variable sizes of jumps. Labelled jumps don't have a size defined, the -- size of a positional jump depends on the address being jumped to. -- -- For example, if jumping to the JUMPDEST on the 256th position -- in a [LabelledOpcode], this requires a PUSH2 -- instruction which uses an additional byte, which pushes the -- JUMPDEST one byte ahead. translate :: [LabelledOpcode] -> Either TranslateError [PositionalOpcode] -- | Extract a Map Label Position that -- describes where each JUMPDEST is located, taking into account -- the sizes of all prior opcodes. labelPositions :: [LabelledOpcode] -> Either TranslateError (Map Label Position) instance GHC.Show.Show EVM.Opcode.Labelled.TranslateError instance GHC.Classes.Eq EVM.Opcode.Labelled.TranslateError