Пример #1
0
 /// <summary>
 /// Our default constructor, sets all properties of our execution result.
 /// </summary>
 /// <param name="evm">The EVM instance which the result is being returned for.</param>
 /// <param name="returnData">Represents data which was returned upon execution of the VM.</param>
 /// <param name="remainingGas">Represents the amount of gas remaining after execution.</param>
 /// <param name="succeeded">Indicates whether or not all changes should be reverted.</param>
 public EVMExecutionResult(MeadowEVM evm, Memory <byte> returnData, BigInteger remainingGas, bool succeeded)
 {
     EVM          = evm;
     ReturnData   = returnData;
     RemainingGas = remainingGas;
     Succeeded    = succeeded;
 }
Пример #2
0
 public void RecordExecutionEnd(MeadowEVM evm)
 {
     // We only keep errors that occurred at the highest level in case an exception occurred in a call, and we accounted for this in our calling contract.
     if (evm.Message.Depth != 0)
     {
         Error = null;
     }
 }
Пример #3
0
        /// <summary>
        /// Creates an instance of the appropriate instruction implementation for this opcode.
        /// </summary>
        /// <returns>Returns the instruction implementation.</returns>
        public InstructionBase GetInstructionImplementation(MeadowEVM evm)
        {
            // Obtain our constructor for this instruction implementation
            ConstructorInfo constructorInfo = ImplementationClassType.GetConstructor(new Type[] { typeof(MeadowEVM) });

            // Invoke the constructor with the appropriate arguments.
            return((InstructionBase)constructorInfo.Invoke(new object[] { evm }));
        }
Пример #4
0
        /// <summary>
        /// Executes the precompile which corresponds to the given address in our provided EVM instance.
        /// </summary>
        /// <param name="evm">The Ethereum Virtual Machine with which we wish to execute the precompile at the provided address.</param>
        /// <param name="address">The address which corresponds to a precompile we wish to execute.</param>
        public static void ExecutePrecompile(MeadowEVM evm, Address address)
        {
            // We obtain the function which we wish to execute.
            var precompileFunction = _precompiles[address];

            // We execute the precompile and set our execution result.
            evm.ExecutionState.Result = precompileFunction(evm);
        }
Пример #5
0
        /// <summary>
        /// A precompiled contract which acts as memcpy, returning a copy of the message data provided.
        /// </summary>
        /// <param name="evm">The Ethereum Virtual Machine instance we are executing inside of.</param>
        private static EVMExecutionResult Precompile_Identity(MeadowEVM evm)
        {
            // Charge the gas for the precompile operation before processing. (A base fee, plus for every word)
            BigInteger gasCharge = GasDefinitions.GAS_PRECOMPILE_IDENTITY_BASE + (EVMDefinitions.GetWordCount(evm.Message.Data.Length) * GasDefinitions.GAS_PRECOMPILE_IDENTITY_WORD);

            evm.GasState.Deduct(gasCharge);

            // We simply return the data back
            return(new EVMExecutionResult(evm, evm.Message.Data, true));
        }
Пример #6
0
        private static EVMExecutionResult Precompile_ECPairing(MeadowEVM evm)
        {
            // Verify we're past the byzantium fork
            if (evm.Version < EthereumRelease.Byzantium)
            {
                return(new EVMExecutionResult(evm, null, true));
            }

            // TODO: Implement
            throw new NotImplementedException();
        }
Пример #7
0
        public EVMExecutionState(MeadowEVM evm)
        {
            // Initialize a new memory segment.
            Memory = new EVMMemory(evm);

            // Initialize the stack.
            Stack = new EVMStack();

            // Set the program counter.
            PC = 0;
        }
Пример #8
0
        private static EVMExecutionResult Precompile_ECAdd(MeadowEVM evm)
        {
            // Verify we're past the byzantium fork
            if (evm.Version < EthereumRelease.Byzantium)
            {
                return(new EVMExecutionResult(evm, null, true));
            }

            // Charge the gas for the precompile operation before processing.
            BigInteger gasCharge = GasDefinitions.GAS_PRECOMPILE_ECADD_BASE;

            evm.GasState.Deduct(gasCharge);

            // Obtain a memory representation of our data.
            Span <byte> messageData = new Span <byte>(evm.Message.Data);

            // Obtain our component data
            BigInteger x1 = BigIntegerConverter.GetBigInteger(messageData.Slice(0, EVMDefinitions.WORD_SIZE));
            BigInteger y1 = BigIntegerConverter.GetBigInteger(messageData.Slice(32, EVMDefinitions.WORD_SIZE));
            BigInteger x2 = BigIntegerConverter.GetBigInteger(messageData.Slice(64, EVMDefinitions.WORD_SIZE));
            BigInteger y2 = BigIntegerConverter.GetBigInteger(messageData.Slice(96, EVMDefinitions.WORD_SIZE));

            // Parse and verify our points.
            FpVector3 <Fp> point1 = ParsePoint(x1, y1);

            if (point1 == null)
            {
                throw new EVMException("ECAdd precompile failed because point 1 was deemed invalid when parsing.");
            }

            FpVector3 <Fp> point2 = ParsePoint(x2, y2);

            if (point1 == null)
            {
                throw new EVMException("ECAdd precompile failed because point 2 was deemed invalid when parsing.");
            }

            // Add the two points together
            FpVector3 <Fp> additionResult = point1.Add(point2);

            // Normalize the result into X/Y components.
            (Fp resultX, Fp resultY) = additionResult.Normalize();

            // Obtain the binary data for these results
            byte[] resultXData = BigIntegerConverter.GetBytes(resultX.N, EVMDefinitions.WORD_SIZE);
            byte[] resultYData = BigIntegerConverter.GetBytes(resultY.N, EVMDefinitions.WORD_SIZE);

            // Concat them to a singular result
            byte[] returnData = resultXData.Concat(resultYData);

            // Return our result
            return(new EVMExecutionResult(evm, returnData, true));
        }
Пример #9
0
        public override void Execute()
        {
            // Obtain the values for our call value, and call data memory.
            BigInteger value            = Stack.Pop();
            BigInteger inputMemoryStart = Stack.Pop();
            BigInteger inputMemorySize  = Stack.Pop();

            // We'll want to charge for memory expansion first
            Memory.ExpandStream(inputMemoryStart, inputMemorySize);

            // If we're in a static context, we can't self destruct
            if (Message.IsStatic)
            {
                throw new EVMException($"{Opcode.ToString()} instruction cannot execute in a static context!");
            }

            // Verify we have enough balance and call depth hasn't exceeded the maximum.
            if (EVM.State.GetBalance(Message.To) >= value && Message.Depth < EVMDefinitions.MAX_CALL_DEPTH)
            {
                // Obtain our call information.
                byte[]     callData     = Memory.ReadBytes((long)inputMemoryStart, (int)inputMemorySize);
                BigInteger innerCallGas = GasState.Gas;
                if (Version >= EthereumRelease.TangerineWhistle)
                {
                    innerCallGas = GasDefinitions.GetMaxCallGas(innerCallGas);
                }

                // Create our message
                EVMMessage         message       = new EVMMessage(Message.To, Address.ZERO_ADDRESS, value, innerCallGas, callData, Message.Depth + 1, Address.ZERO_ADDRESS, true, Message.IsStatic);
                EVMExecutionResult innerVMResult = MeadowEVM.CreateContract(EVM.State, message);
                if (innerVMResult.Succeeded)
                {
                    // Push our resulting address onto the stack.
                    Stack.Push(BigIntegerConverter.GetBigInteger(innerVMResult.ReturnData.ToArray()));
                    EVM.ExecutionState.LastCallResult = null;
                }
                else
                {
                    // We failed, push our fail value and put the last call data in place.
                    Stack.Push(0);
                    ExecutionState.LastCallResult = innerVMResult;
                }
            }
            else
            {
                // We didn't have a sufficient balance or call depth so we push nothing to the stack. We push 0 (fail)
                Stack.Push(0);

                // Set our last call result as null.
                ExecutionState.LastCallResult = null;
            }
        }
Пример #10
0
        /// <summary>
        /// Our constructor, takes a byte array to map virtual memory to.
        /// </summary>
        /// <param name="evm">The parent EVM that this memory belongs to (and gas should be charged to).</param>
        /// <param name="memoryData">The byte array to map virtual memory to.</param>
        public EVMMemory(MeadowEVM evm, byte[] memoryData)
        {
            // Set our evm and stream
            EVM = evm;
            _internalBufferStream = new MemoryStream();
            if (memoryData != null && memoryData.Length != 0)
            {
                _internalBufferStream.Write(memoryData, 0, memoryData.Length);
                _internalBufferStream.Position = 0;
            }

            ChangeCount = 0;
        }
Пример #11
0
        /// <summary>
        /// A precompiled contract which computes a SHA256 hash from the message data.
        /// </summary>
        /// <param name="evm">The Ethereum Virtual Machine instance we are executing inside of.</param>
        private static EVMExecutionResult Precompile_SHA256(MeadowEVM evm)
        {
            // Charge the gas for the precompile operation before processing. (A base fee, plus for every word)
            BigInteger gasCharge = GasDefinitions.GAS_PRECOMPILE_SHA256_BASE + (EVMDefinitions.GetWordCount(evm.Message.Data.Length) * GasDefinitions.GAS_PRECOMPILE_SHA256_WORD);

            evm.GasState.Deduct(gasCharge);

            // We compute a hash of the message data.
            byte[] hash = SHA256.Create().ComputeHash(evm.Message.Data);

            // Return the hash
            return(new EVMExecutionResult(evm, hash, true));
        }
Пример #12
0
        /// <summary>
        /// Our default constructor, reads the opcode/operand information from the provided stream.
        /// </summary>
        public InstructionBase(MeadowEVM evm)
        {
            // Set our virtual machine
            EVM = evm;

            // Set our code address in case we need to know it (by execution time it will be advanced past it)
            Offset = ExecutionState.PC;

            // We read our opcode
            Opcode = (InstructionOpcode)evm.Code.Span[(int)Offset];

            // Advance our program counter
            ExecutionState.PC++;
        }
Пример #13
0
        /// <summary>
        /// A precompiled contract which computes a RIPEMD160 hash from the message data.
        /// </summary>
        /// <param name="evm">The Ethereum Virtual Machine instance we are executing inside of.</param>
        private static EVMExecutionResult Precompile_RIPEMD160(MeadowEVM evm)
        {
            // Charge the gas for the precompile operation before processing. (A base fee, plus for every word)
            BigInteger gasCharge = GasDefinitions.GAS_PRECOMPILE_RIPEMD160_BASE + (EVMDefinitions.GetWordCount(evm.Message.Data.Length) * GasDefinitions.GAS_PRECOMPILE_RIPEMD160_WORD);

            evm.GasState.Deduct(gasCharge);

            // We compute a hash of the message data.
            byte[] hash = new RIPEMD160Managed().ComputeHash(evm.Message.Data);

            // We make the return value into the size of a word.
            byte[] result = new byte[EVMDefinitions.WORD_SIZE];
            Array.Copy(hash, 0, result, result.Length - hash.Length, hash.Length);

            // Return the result
            return(new EVMExecutionResult(evm, result, true));
        }
Пример #14
0
        // Precompiles Below
        /// <summary>
        /// A precompiled contract which uses v,r,s + hash obtained from the message data to perform elliptic curve public key recovery to obtain a senders address.
        /// </summary>
        /// <param name="evm">The Ethereum Virtual Machine instance we are executing inside of.</param>
        private static EVMExecutionResult Precompile_ECRecover(MeadowEVM evm)
        {
            // Charge the gas for the precompile operation before processing.
            evm.GasState.Deduct(GasDefinitions.GAS_PRECOMPILE_ECRECOVER);

            // Obtain a memory representation of our data.
            Span <byte> messageData = new Span <byte>(evm.Message.Data);

            // We extract our signature information from message data (256-bit each)
            Span <byte> hash = messageData.Slice(0, EVMDefinitions.WORD_SIZE);
            BigInteger  v    = BigIntegerConverter.GetBigInteger(messageData.Slice(32, EVMDefinitions.WORD_SIZE));
            BigInteger  r    = BigIntegerConverter.GetBigInteger(messageData.Slice(64, EVMDefinitions.WORD_SIZE));
            BigInteger  s    = BigIntegerConverter.GetBigInteger(messageData.Slice(96, EVMDefinitions.WORD_SIZE));

            // Verify we have a low r, s, and a valid v.
            if (r >= Secp256k1Curve.N || s >= Secp256k1Curve.N || v < 27 || v > 28)
            {
                // We failed v,r,s verification, so we stop executing.
                return(new EVMExecutionResult(evm, null, true));
            }

            // Obtain our recovery id from v.
            byte recoveryID = EthereumEcdsa.GetRecoveryAndChainIDFromV((byte)v).recoveryId;

            // Try to get an address from this. If it fails, it will throw an exception.
            byte[] senderAddress = null;
            try
            {
                senderAddress = EthereumEcdsa.Recover(hash, recoveryID, r, s).GetPublicKeyHash();
            }
            catch
            {
                // Recovery failed, so we stop executing.
                return(new EVMExecutionResult(evm, null, true));
            }

            // The address portion is at the end, and we zero out the leading portion.
            for (int i = 0; i < senderAddress.Length - Address.ADDRESS_SIZE; i++)
            {
                senderAddress[i] = 0;
            }

            // Return the sender address
            return(new EVMExecutionResult(evm, senderAddress, true));
        }
        public void InstructionStackChangeTest()
        {
            // Get a list of all opcodes
            InstructionOpcode[] opcodes = (InstructionOpcode[])Enum.GetValues(typeof(InstructionOpcode));

            // Create a new state
            var   configuration = new Configuration.Configuration();
            State state         = configuration.GenesisStateSnapshot.ToState();

            // Create an EVM.
            var evm = new MeadowEVM();

            evm.State          = state;
            evm.ExecutionState = new Meadow.EVM.EVM.Execution.EVMExecutionState(evm);
            evm.GasState       = new Meadow.EVM.EVM.Execution.EVMGasState(int.MaxValue);
            evm.Message        = new Meadow.EVM.EVM.Messages.EVMMessage("0", "0", 0, int.MaxValue, Array.Empty <byte>(), 0, "0", true, false);
            evm.Code           = new byte[EVMDefinitions.MAX_CONTRACT_SIZE];

            // Push a bunch of nonsense data to the stack (we choose the value to minimize error)
            for (int i = 0; i < 100; i++)
            {
                evm.ExecutionState.Stack.Push(1);
            }

            foreach (InstructionOpcode opcode in opcodes)
            {
                // Obtain our instruction.
                var opcodeDescriptor = opcode.GetDescriptor();
                var instruction      = opcodeDescriptor.GetInstructionImplementation(evm);

                // Backup our stack size
                int stackSize = evm.ExecutionState.Stack.Count;

                try
                {
                    // Execute.
                    instruction.Execute();
                }
                catch { continue; }
                Assert.Equal(stackSize + ((int)opcodeDescriptor.ItemsAddedToStack - (int)opcodeDescriptor.ItemsRemovedFromStack), evm.ExecutionState.Stack.Count);
            }
        }
Пример #16
0
        /// <summary>
        /// Our default constructor, reads the opcode/operand information from the provided stream.
        /// </summary>
        public InstructionPush(MeadowEVM evm) : base(evm)
        {
            // This class handles multiple push operations (various sizes).
            // The opcodes are linear, so we can calculate the size of the push based off opcode.
            PushSize = (uint)(Opcode - InstructionOpcode.PUSH1) + 1;

            // Assert we are not at the end of the code.
            if (EVM.Code.Length < (ExecutionState.PC + PushSize))
            {
                throw new EVMException($"Cannot read {OpcodeDescriptor.Mnemonic}'s operand because the end of the stream was reached, or the bytes to read were unavailable.");
            }

            // Read our push data.
            byte[] pushBytes = EVM.Code.Slice((int)ExecutionState.PC, (int)PushSize).ToArray();

            // Parse our push data as a uint256.
            PushData = BigIntegerConverter.GetBigInteger(pushBytes);

            // Advance our program counter
            ExecutionState.PC += PushSize;
        }
Пример #17
0
        // Tracing
        public void RecordExecutionStart(MeadowEVM evm)
        {
            // If we're not tracing, clear our execution trace.
            if (!IsTracing)
            {
                ExecutionTrace = null;
            }

            // If our depth is 0, we should start a new trace map and clear errors.
            if (evm.Message.Depth == 0)
            {
                // Start a new trace map if we're tracing.
                if (IsTracing)
                {
                    ExecutionTrace = new ExecutionTrace();
                }

                // Clear our error.
                Error = null;
            }
        }
Пример #18
0
 /// <summary>
 /// Our default constructor, reads the opcode/operand information from the provided stream.
 /// </summary>
 public InstructionJump(MeadowEVM evm) : base(evm)
 {
 }
Пример #19
0
 /// <summary>
 /// Our default constructor, reads the opcode/operand information from the provided stream.
 /// </summary>
 public InstructionAddMod(MeadowEVM evm) : base(evm)
 {
 }
Пример #20
0
        public void RecordExecution(MeadowEVM evm, InstructionBase instruction, BigInteger gasRemaining, BigInteger gasCost)
        {
            // Obtain our deployed address and status
            Address deployedAddress = evm.Message.GetDeployedCodeAddress();
            bool    isDeployed      = deployedAddress == evm.Message.CodeAddress;

            // Declare our memory + last returned data, null initially (indicating it is unchanged from the last known value).
            byte[] memory = null;

            // Determine if our context has changed between contracts, or our memory has changed.
            bool contextChanged = _lastContractAddress != deployedAddress;
            bool memoryChanged  = _lastMemoryChangeCount != evm.ExecutionState.Memory.ChangeCount;

            // If our context or memory has changed, we'll want to include the memory. (This way our simple lookup for memory will consist of checking in the current trace point, or if null, loop backwards to the last one you find).
            if (contextChanged || memoryChanged)
            {
                memory = evm.ExecutionState.Memory.ToArray();
            }

            // Update our last processed contract address and change count
            _lastContractAddress   = deployedAddress;
            _lastMemoryChangeCount = evm.ExecutionState.Memory.ChangeCount;

            // Determine if our storage changed
            bool storageChanged = instruction is InstructionStorageStore;

            // Determine our storage we will have for this point (null if unchanged, otherwise set)
            Dictionary <Memory <byte>, byte[]> storage = null;

            if (contextChanged || storageChanged)
            {
                // Obtain our storage dictionary.
                var account = evm.State.GetAccount(evm.Message.To);
                storage = account.StorageTrie.ToDictionary();

                // Apply all in progress edits.
                foreach (var key in account.StorageCache.Keys)
                {
                    // Obtain our value from our storage cache.
                    var value = account.StorageCache[key];

                    // If it's zero bytes, it's an entry to be removed, otherwise we set it.
                    if (value == null || value.Length == 0)
                    {
                        storage.Remove(key);
                    }
                    else
                    {
                        storage[key] = value;
                    }
                }
            }

            // If our context changed, we want to include code hash.
            byte[] codeSegment = null;
            if (contextChanged)
            {
                codeSegment = evm.Code.ToArray();
            }

            // Add a new tracepoint.
            var tracePoint = new ExecutionTracePoint()
            {
                Code             = codeSegment,
                ContractAddress  = contextChanged ? deployedAddress : null,
                ContractDeployed = isDeployed,
                Depth            = (uint)evm.Message.Depth,
                Opcode           = instruction.OpcodeDescriptor.Mnemonic,
                PC           = instruction.Offset,
                GasRemaining = gasRemaining,
                GasCost      = gasCost,
                Stack        = evm.ExecutionState.Stack.ToArray(),
                Memory       = memory,
                Storage      = storage
            };

            // Add it to our list.
            Tracepoints.Add(tracePoint);
        }
Пример #21
0
 /// <summary>
 /// Our default constructor, reads the opcode/operand information from the provided stream.
 /// </summary>
 public InstructionGreaterThan(MeadowEVM evm) : base(evm)
 {
 }
Пример #22
0
 /// <summary>
 /// Our default constructor, reads the opcode/operand information from the provided stream.
 /// </summary>
 public InstructionBlockCoinbase(MeadowEVM evm) : base(evm)
 {
 }
Пример #23
0
 /// <summary>
 /// Our default constructor, reads the opcode/operand information from the provided stream.
 /// </summary>
 public InstructionSHA3(MeadowEVM evm) : base(evm)
 {
 }
Пример #24
0
        private static EVMExecutionResult Precompile_ModExp(MeadowEVM evm)
        {
            // Verify we're past the byzantium fork
            if (evm.Version < EthereumRelease.Byzantium)
            {
                return(new EVMExecutionResult(evm, null, true));
            }

            // Source: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-198.md

            // Obtain a memory representation of our data.
            Span <byte> messageData = new Memory <byte>(evm.Message.Data).Span;

            // Extract our base length, exponent length, and mod length (in bytes)
            BigInteger baseLength     = BigIntegerConverter.GetBigInteger(messageData.Slice(0, EVMDefinitions.WORD_SIZE));
            BigInteger exponentLength = BigIntegerConverter.GetBigInteger(messageData.Slice(32, EVMDefinitions.WORD_SIZE));
            BigInteger modLength      = BigIntegerConverter.GetBigInteger(messageData.Slice(64, EVMDefinitions.WORD_SIZE));

            // GAS CALCULATION START: Exponent is leading the word of data, so we obtain a numeric representation of the first bytes.
            BigInteger exponentHead = BigIntegerConverter.GetBigInteger(messageData.Slice(96 + (int)baseLength, EVMDefinitions.WORD_SIZE));

            // Shift our head so we only have relevant bytes (they're leading the word, so we want to cut the tail off by bitshifting).
            exponentHead >>= (8 * (int)BigInteger.Max(32 - exponentLength, 0));

            // Count our bits in our exponent head.
            int exponentHeadBitCount = -1;

            while (exponentHead > 0)
            {
                exponentHead >>= 1;
                exponentHeadBitCount++;
            }

            // Obtain our adjusted exponent length.
            // 1) If exponent length <= 32, and exponent bits are 0, this is 0.
            // 2) If exponent length <= 32, then return the index of the highest bit in exponent.
            // 3) If exponent length > 32, then we return (8 * (exponent-length - 32)) + the index of the highest bit in the exponent.
            BigInteger adjustedExponentLength = Math.Max(exponentHeadBitCount, 0) + (8 * BigInteger.Max(exponentLength - 32, 0));

            adjustedExponentLength = BigInteger.Max(adjustedExponentLength, 1);

            // GAS CALCULATION END: Calculate the final gas cost from the length of our biggest parameter, times the exponent length, divided by our divisor.
            BigInteger biggestLength = BigInteger.Max(modLength, baseLength);
            BigInteger gasCost       = (Estimate_karatsuba_difficulty(biggestLength) * adjustedExponentLength) / GasDefinitions.GAS_PRECOMPILE_MODEXP_QUAD_DIVISOR;

            // Deduct our gas cost.
            evm.GasState.Deduct(gasCost);

            // Verify our base length.
            if (baseLength == 0)
            {
                return(new EVMExecutionResult(evm, new byte[(int)modLength], true));
            }

            // Verify our mod length.
            if (modLength == 0)
            {
                return(new EVMExecutionResult(evm, null, true));
            }

            // Obtain our base, exponent and mod
            Span <byte> memBase     = messageData.Slice(96, (int)baseLength);
            BigInteger  numBase     = BigIntegerConverter.GetBigInteger(memBase, false, memBase.Length);
            Span <byte> memExponent = messageData.Slice(96 + (int)baseLength, (int)exponentLength);
            BigInteger  numExponent = BigIntegerConverter.GetBigInteger(memExponent, false, memExponent.Length);
            Span <byte> memMod      = messageData.Slice(96 + (int)baseLength + (int)exponentLength, (int)modLength);
            BigInteger  numMod      = BigIntegerConverter.GetBigInteger(memMod, false, memMod.Length);

            // Verify our divisor isn't 0.
            if (numMod == 0)
            {
                return(new EVMExecutionResult(evm, new byte[(int)modLength], true));
            }

            // Obtain our modexp result, which, by definition, we know won't be bigger than our divisor, so we bind our length to the modulo divisor length.
            BigInteger numResult = BigInteger.ModPow(numBase, numExponent, numMod);

            byte[] result = BigIntegerConverter.GetBytes(numResult, (int)modLength);

            // Return our result
            return(new EVMExecutionResult(evm, result, true));
        }
Пример #25
0
 /// <summary>
 /// Our default constructor, reads the opcode/operand information from the provided stream.
 /// </summary>
 public InstructionExponent(MeadowEVM evm) : base(evm)
 {
 }
Пример #26
0
 /// <summary>
 /// Our default constructor, reads the opcode/operand information from the provided stream.
 /// </summary>
 public InstructionCreate(MeadowEVM evm) : base(evm)
 {
 }
Пример #27
0
 /// <summary>
 /// Our default constructor, reads the opcode/operand information from the provided stream.
 /// </summary>
 public InstructionMemoryStore(MeadowEVM evm) : base(evm)
 {
 }
Пример #28
0
 /// <summary>
 /// Our default constructor, reads the opcode/operand information from the provided stream.
 /// </summary>
 public InstructionExternalCodeSize(MeadowEVM evm) : base(evm)
 {
 }
Пример #29
0
 /// <summary>
 /// Our default constructor, reads the opcode/operand information from the provided stream.
 /// </summary>
 public InstructionReturnDataSize(MeadowEVM evm) : base(evm)
 {
 }
Пример #30
0
 /// <summary>
 /// Our default constructor, reads the opcode/operand information from the provided stream.
 /// </summary>
 public InstructionLog(MeadowEVM evm) : base(evm)
 {
 }