Beispiel #1
0
 public SolidityProgramInvoke(IEnumerable <byte> smartContractAddress, DataWord ownerAddress, DataWord callValue, SmartContracts smartContracts)
 {
     _smartContractAddress = smartContractAddress;
     _ownerAddress         = ownerAddress;
     _callValue            = callValue;
     _smartContracts       = smartContracts;
 }
Beispiel #2
0
        public DataWord GetDataValue(DataWord indexData)
        {
            byte[] data  = new byte[_size];
            var    index = indexData.GetValue().IntValue;
            int    size  = _size;

            if (_msgDataRaw == null)
            {
                return(new DataWord(data));
            }

            if (index > _msgDataRaw.Count())
            {
                return(new DataWord(data));
            }

            if (index + _size > _msgDataRaw.Count())
            {
                size = _msgDataRaw.Count() - index;
            }

            var res = _msgDataRaw.Skip(index).Take(size).ToList();

            for (int i = res.Count(); i < _size; i++)
            {
                res.Add(0);
            }

            return(new DataWord(res.ToArray()));
        }
        public SolidityExecutor Execute(IEnumerable <byte> scAddrPayload, IEnumerable <byte> addrPayload, IEnumerable <byte> data, bool addInTransaction = false)
        {
            if (scAddrPayload == null)
            {
                throw new ArgumentNullException(nameof(scAddrPayload));
            }

            if (addrPayload == null)
            {
                addrPayload = new byte[0];
            }

            var smartContract    = _smartContractStore.GetSmartContracts().GetSmartContract(scAddrPayload);
            var defaultCallValue = new DataWord(new byte[] { 0x00 });

            _smartContracts = _smartContractStore.GetSmartContracts();
            var scode = smartContract.Code.ToHexString();

            _solidityProgram = new SolidityProgram(smartContract.Code.ToList(), new SolidityProgramInvoke(data, smartContract.Address, new DataWord(addrPayload.ToArray()), defaultCallValue, _smartContracts, addInTransaction));
            var vm = new SolidityVm();

            while (!_solidityProgram.IsStopped())
            {
                vm.Step(_solidityProgram);
            }

            return(this);
        }
Beispiel #4
0
        public DataWord GetStorageRow(IEnumerable <byte> scAddr, DataWord key)
        {
            if (scAddr == null)
            {
                throw new ArgumentNullException(nameof(scAddr));
            }

            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            var result    = string.Empty;
            var scAddrHex = scAddr.ToHexString();
            var keyHex    = key.GetData().ToHexString();

            if (!_db.TryGet(string.Format(SMART_CONTRACT_STORE_ELT, scAddrHex, keyHex), ReadOptions.Default, out result))
            {
                var cacheDataRow = _cacheDataRows.FirstOrDefault(c => c.Key == string.Format(SMART_CONTRACT_STORE_ELT, scAddrHex, keyHex));
                if (cacheDataRow.Equals(default(KeyValuePair <string, string>)) || string.IsNullOrWhiteSpace(cacheDataRow.Value))
                {
                    return(DataWord.ZERO);
                }

                return(new DataWord(cacheDataRow.Value.FromHexString().ToArray()));
            }

            return(new DataWord(result.FromHexString().ToArray()));
        }
 public void MemoryExpand(DataWord outDataOffs, DataWord outDataSize)
 {
     if (!outDataSize.IsZero())
     {
         _memory.Extend(outDataOffs.GetInt(), outDataSize.GetInt());
     }
 }
Beispiel #6
0
        public IEnumerable <byte> GetDataCopy(DataWord offsetData, DataWord lengthData)
        {
            var offset = offsetData.GetValue().IntValue;
            var length = lengthData.GetValue().IntValue;

            byte[] data = new byte[length];
            if (_msgDataRaw == null)
            {
                return(data);
            }

            if (offset > _msgDataRaw.Count())
            {
                return(data);
            }

            var res = _msgDataRaw.Skip(offset).Take(length).ToList();
            var mod = res.Count % _size;

            if (mod != 0)
            {
                for (int i = 0; i < (_size - mod); i++)
                {
                    res.Add(0);
                }
            }

            return(res);
        }
Beispiel #7
0
 public DataWord XOR(DataWord w2)
 {
     for (int i = 0; i < _data.Count(); ++i)
     {
         _data[i] ^= w2.GetData()[i];
     }
     return(this);
 }
        public void SaveStorage(IEnumerable <byte> key, IEnumerable <byte> val)
        {
            var scAddr  = _progInvoke.GetSmartContractAddress();
            var keyWord = new DataWord(key.ToArray());
            var valWord = new DataWord(val.ToArray());

            _progInvoke.GetStorage().AddStorageRow(scAddr, keyWord, valWord, _progInvoke.GetAddInTransaction());
        }
Beispiel #9
0
 public SolidityProgramInvoke(IEnumerable <byte> msgDataRaw, IEnumerable <byte> smartContractAddress, DataWord ownerAddress, DataWord callValue, SmartContracts smartContracts, bool addInTransaction = false)
 {
     _msgDataRaw           = msgDataRaw;
     _smartContractAddress = smartContractAddress;
     _ownerAddress         = ownerAddress;
     _callValue            = callValue;
     _smartContracts       = smartContracts;
     _addInTransaction     = addInTransaction;
 }
Beispiel #10
0
 public static SolidityPrecompiledContract GetContractForAddress(DataWord address)
 {
     if (address == null)
     {
         return(_identity);
     }
     if (address.Equals(_identityAddr))
     {
         return(_identity);
     }
     return(null);
 }
Beispiel #11
0
        public void Div(DataWord word)
        {
            if (word.IsZero())
            {
                this.And(ZERO);
                return;
            }

            BigInteger result = GetValue().Divide(word.GetValue());

            _data = ByteUtil.CopyToArray(result.And(MAX_VALUE));
        }
Beispiel #12
0
        public void Add(DataWord word)
        {
            byte[] result = new byte[32];
            for (int i = 31, overflow = 0; i >= 0; i--)
            {
                int v = (_data[i] & 0xff) + (word.GetData()[i] & 0xff) + overflow;
                result[i] = (byte)v;
                overflow  = v >> 8;
            }

            _data = result;
        }
Beispiel #13
0
        public bool AddStorageRow(IEnumerable <byte> scAddr, DataWord key, DataWord value, bool addInTransaction = false)
        {
            if (scAddr == null)
            {
                throw new ArgumentNullException(nameof(scAddr));
            }

            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            var writeBatch = new WriteBatch();

            if (addInTransaction)
            {
                writeBatch = _writeBatch;
            }

            string result    = string.Empty;
            var    scAddrHex = scAddr.ToHexString();
            var    keyHex    = key.GetData().ToHexString();
            var    valueHex  = value.GetData().ToHexString();

            if (!_db.TryGet(string.Format(SMART_CONTRACT_ELT, scAddrHex), ReadOptions.Default, out result))
            {
                return(false);
            }

            result = string.Empty;
            if (_db.TryGet(string.Format(SMART_CONTRACT_STORE_ELT, scAddrHex, keyHex), ReadOptions.Default, out result))
            {
                writeBatch.Delete(string.Format(SMART_CONTRACT_STORE_ELT, scAddrHex, keyHex));
            }

            writeBatch.Put(string.Format(SMART_CONTRACT_STORE_ELT, scAddrHex, keyHex), valueHex);
            if (!addInTransaction)
            {
                _db.Write(writeBatch, WriteOptions.Default);
            }
            else
            {
                _cacheDataRows.Add(string.Format(SMART_CONTRACT_STORE_ELT, scAddrHex, keyHex), keyHex);
            }

            return(true);
        }
        public int VerifyJumpDest(DataWord nextPC)
        {
            if (nextPC.GetBytesOccupied() > 4)
            {
                throw new InvalidOperationException("Bad jump destination");
            }

            int ret = nextPC.GetInt();

            if (!GetProgramPrecompile().HasJumpDest(ret))
            {
                throw new InvalidOperationException("Bad jump destination");
            }

            return(ret);
        }
Beispiel #15
0
 public void SetOwnerAddress(DataWord address)
 {
     _ownerAddress = address;
 }
Beispiel #16
0
        public void Exp(DataWord word)
        {
            var result = GetValue().ModPow(word.GetValue(), _2_256);

            _data = ByteUtil.CopyToArray(result);
        }
Beispiel #17
0
        public void Sub(DataWord word)
        {
            BigInteger result = GetValue().Subtract(word.GetValue());

            _data = ByteUtil.CopyToArray(result.And(MAX_VALUE));
        }
Beispiel #18
0
        public void Mul(DataWord word)
        {
            BigInteger result = GetValue().Multiply(word.GetValue());

            _data = ByteUtil.CopyToArray(result.And(MAX_VALUE));
        }
 public DataWord LoadMemory(DataWord addr)
 {
     return(_memory.ReadWord(addr.GetInt()));
 }
Beispiel #20
0
        private void Persist(Block block, WriteBatch writeBatch, bool addIntoCache = false)
        {
            if (writeBatch == null)
            {
                throw new ArgumentNullException(nameof(writeBatch));
            }

            if (block == null)
            {
                throw new ArgumentNullException(nameof(block));
            }

            var defaultCallValue = new DataWord(new byte[] { 0x00 });

            foreach (var transaction in block.Transactions)
            {
                var smartContractTransaction = transaction as SmartContractTransaction;
                if (smartContractTransaction == null)
                {
                    continue;
                }


                if (smartContractTransaction.To == null || !smartContractTransaction.To.Any()) // Create the contract.
                {
                    var solidityVm = new SolidityVm();
                    var program    = new SolidityProgram(smartContractTransaction.Data.ToList(), new SolidityProgramInvoke(new byte[0], new DataWord(smartContractTransaction.From.ToArray()), defaultCallValue, this));
                    while (!program.IsStopped())
                    {
                        solidityVm.Step(program);
                    }

                    var contractCode     = program.GetResult().GetHReturn();
                    var txId             = transaction.GetTxId();
                    var smartContractAdr = smartContractTransaction.GetSmartContractAddress();
                    var hex = contractCode.ToHexString();
                    writeBatch.Put(string.Format(SMART_CONTRACT_ELT, smartContractAdr.ToHexString()), hex);
                    writeBatch.Put(string.Format(SMART_CONTRACT_TX_ELT, txId.ToHexString()), smartContractAdr.ToHexString());
                    if (addIntoCache)
                    {
                        _cacheSmartContracts.Add(smartContractAdr.ToHexString(), new SmartContract
                        {
                            Address = smartContractAdr,
                            Code    = contractCode
                        });
                        _cacheTxSmartContracts.Add(txId.ToHexString(), new SmartContract
                        {
                            Address = smartContractAdr,
                            Code    = contractCode
                        });
                    }
                }
                else if (smartContractTransaction.To != null)
                {
                    var sc = GetSmartContract(smartContractTransaction.To);
                    if (sc == null)
                    {
                        return;
                    }

                    var from = smartContractTransaction.From;
                    if (from == null)
                    {
                        from = new byte[0];
                    }

                    var solidityVm = new SolidityVm();
                    var program    = new SolidityProgram(sc.Code.ToList(), new SolidityProgramInvoke(smartContractTransaction.Data, smartContractTransaction.To, new DataWord(from.ToArray()), defaultCallValue, this));
                    while (!program.IsStopped())
                    {
                        solidityVm.Step(program);
                    }

                    var logs = program.GetResult().GetLogs();
                    if (logs != null && logs.Any())
                    {
                        AddLogs(smartContractTransaction.To, block.GetHashHeader(), logs, addIntoCache);
                    }
                }
            }
        }
 public IEnumerable <byte> GetDataCopy(DataWord offsetData, DataWord lengthData)
 {
     return(_progInvoke.GetDataCopy(offsetData, lengthData));
 }
 public DataWord GetDataValue(DataWord data)
 {
     return(_progInvoke.GetDataValue(data));
 }
 public void StackPush(DataWord data)
 {
     _stack.Add(data);
 }
Beispiel #24
0
 private static BigInteger MemNeeded(DataWord offset, DataWord size)
 {
     return(size.IsZero() ? BigInteger.Zero : offset.GetValue().Add(size.GetValue()));
 }
 public void SaveMemory(DataWord addrB, DataWord value)
 {
     _memory.Write(addrB.GetInt(), value.GetData(), value.GetData().Length, false);
 }
        public void SaveStorage(DataWord w1, DataWord w2)
        {
            var scAddr = _progInvoke.GetSmartContractAddress();

            _progInvoke.GetStorage().AddStorageRow(scAddr, w1, w2, _progInvoke.GetAddInTransaction());
        }
Beispiel #27
0
        public void Step(SolidityProgram program, bool trace = false)
        {
            if (program == null) // http://solidity.readthedocs.io/en/develop/assembly.html
            {
                throw new ArgumentNullException(nameof(program));
            }

            var  solidityOpCode = SolidityOpCode.Instance();
            var  currentOpCode  = program.GetCurrentOpCode();
            var  opCode         = solidityOpCode.GetCode(currentOpCode);
            var  stack          = program.GetStack();
            var  oldMemSize     = program.GetMemorySize();
            long gasCost        = (long)solidityOpCode.GetTier(opCode.Value);

            switch (opCode)
            {
            case SolidityOpCodes.STOP:
                gasCost = SolidityGasCost.STOP;
                break;

            case SolidityOpCodes.SUICIDE:
                gasCost = SolidityGasCost.SUICIDE;
                break;

            case SolidityOpCodes.SSTORE:
                var sstoreNewValue = stack.ElementAt(stack.Count() - 2);
                var sstoreOldValue = program.StorageLoad(stack.Last());
                if (sstoreOldValue == null || !sstoreOldValue.IsZero())
                {
                    gasCost = SolidityGasCost.SET_SSTORE;
                }
                else if (sstoreOldValue != null && sstoreNewValue.IsZero())
                {
                    gasCost = SolidityGasCost.CLEAR_SSTORE;
                }
                else
                {
                    gasCost = SolidityGasCost.RESET_SSTORE;
                }
                break;

            case SolidityOpCodes.SLOAD:
                gasCost = SolidityGasCost.SLOAD;
                break;

            case SolidityOpCodes.MSTORE:
                gasCost += CalcMemGas(oldMemSize, MemNeeded(stack.Last(), new DataWord(32)), 0);
                break;

            case SolidityOpCodes.MSTORE8:
                gasCost += CalcMemGas(oldMemSize, MemNeeded(stack.Last(), new DataWord(1)), 0);
                break;

            case SolidityOpCodes.MLOAD:
                gasCost += CalcMemGas(oldMemSize, MemNeeded(stack.Last(), new DataWord(32)), 0);
                break;

            case SolidityOpCodes.RETURN:
            case SolidityOpCodes.REVERT:
                gasCost = SolidityGasCost.STOP + CalcMemGas(oldMemSize, MemNeeded(stack.Last(), stack.ElementAt(stack.Count() - 2)), 0);
                break;

            case SolidityOpCodes.SHA3:
                gasCost = SolidityGasCost.SHA3 + CalcMemGas(oldMemSize, MemNeeded(stack.Last(), stack.ElementAt(stack.Count() - 2)), 0);
                var size      = stack.ElementAt(stack.Count() - 2);
                var chunkUsed = (size.GetLongValueSafe() + 31) / 32;
                gasCost += chunkUsed * SolidityGasCost.SHA3_WORD;
                break;

            case SolidityOpCodes.CALLDATACOPY:
            case SolidityOpCodes.RETURNDATACOPY:
                gasCost += CalcMemGas(oldMemSize, MemNeeded(stack.Last(), stack.ElementAt(stack.Count() - 3)),
                                      stack.ElementAt(stack.Count() - 3).GetLongValueSafe());
                break;

            case SolidityOpCodes.CODECOPY:
                gasCost += CalcMemGas(oldMemSize,
                                      MemNeeded(stack.Last(), stack.ElementAt(stack.Count() - 3)),
                                      stack.ElementAt(stack.Count() - 3).GetLongValueSafe());
                break;

            case SolidityOpCodes.EXTCODESIZE:
                gasCost = SolidityGasCost.EXT_CODE_SIZE;
                break;

            case SolidityOpCodes.EXTCODECOPY:
                gasCost = SolidityGasCost.EXT_CODE_COPY + CalcMemGas(oldMemSize,
                                                                     MemNeeded(stack.ElementAt(stack.Count() - 2), stack.ElementAt(stack.Count() - 4)),
                                                                     stack.ElementAt(stack.Count() - 4).GetLongValueSafe());
                break;

            case SolidityOpCodes.CALL:
            // case SolidityOpCodes.CALLCODE:
            case SolidityOpCodes.DELEGATECALL:
            case SolidityOpCodes.STATICCALL:

                gasCost = SolidityGasCost.CALL;
                var callGasWord     = stack.ElementAt(stack.Count() - 1);
                var callAddressWord = stack.ElementAt(stack.Count() - 2);
                var value           = DataWord.ZERO;

                /*
                 * DataWord value = op.callHasValue() ?
                 *      stack.get(stack.size() - 3) : DataWord.ZERO;
                 */
                if (opCode == SolidityOpCodes.CALL)
                {
                    gasCost += SolidityGasCost.NEW_ACCT_CALL;
                }

                if (!value.IsZero())
                {
                    gasCost += SolidityGasCost.VT_CALL;
                }

                break;

            case SolidityOpCodes.EXP:

                DataWord exp           = stack.ElementAt(stack.Count() - 2);
                int      bytesOccupied = exp.GetBytesOccupied();
                gasCost = SolidityGasCost.EXP_GAS + SolidityGasCost.EXP_BYTE_GAS * bytesOccupied;
                break;
            }

            if (trace)
            {
                Trace.WriteLine("Operation " + Enum.GetName(typeof(SolidityOpCodes), opCode) + " " + program.GetPc() + " COST = " + gasCost);
                Trace.WriteLine("Stack: ");
                foreach (var s in program.GetStack())
                {
                    Trace.WriteLine(s.GetData().ToHexString());
                }

                Trace.WriteLine("Memory: ");
                Trace.WriteLine(program.GetMemory().ToHexString());
            }

            switch (opCode)
            {
            case SolidityOpCodes.PUSH1:
            case SolidityOpCodes.PUSH2:
            case SolidityOpCodes.PUSH3:
            case SolidityOpCodes.PUSH4:
            case SolidityOpCodes.PUSH5:
            case SolidityOpCodes.PUSH6:
            case SolidityOpCodes.PUSH7:
            case SolidityOpCodes.PUSH8:
            case SolidityOpCodes.PUSH9:
            case SolidityOpCodes.PUSH10:
            case SolidityOpCodes.PUSH11:
            case SolidityOpCodes.PUSH12:
            case SolidityOpCodes.PUSH13:
            case SolidityOpCodes.PUSH14:
            case SolidityOpCodes.PUSH15:
            case SolidityOpCodes.PUSH16:
            case SolidityOpCodes.PUSH17:
            case SolidityOpCodes.PUSH18:
            case SolidityOpCodes.PUSH19:
            case SolidityOpCodes.PUSH20:
            case SolidityOpCodes.PUSH21:
            case SolidityOpCodes.PUSH22:
            case SolidityOpCodes.PUSH23:
            case SolidityOpCodes.PUSH24:
            case SolidityOpCodes.PUSH25:
            case SolidityOpCodes.PUSH26:
            case SolidityOpCodes.PUSH27:
            case SolidityOpCodes.PUSH28:
            case SolidityOpCodes.PUSH29:
            case SolidityOpCodes.PUSH30:
            case SolidityOpCodes.PUSH31:
            case SolidityOpCodes.PUSH32:
                if (opCode == SolidityOpCodes.PUSH32)
                {
                    string sss = "";
                }
                program.Step();
                var nPush = SizeSolidityCodes[opCode.Value];
                var data  = program.Sweep(nPush);
                program.StackPush(data);
                break;

            case SolidityOpCodes.CALLDATALOAD:
                var pop       = program.StackPop();
                var dataValue = program.GetDataValue(pop);
                program.StackPush(dataValue);
                program.Step();
                break;

            case SolidityOpCodes.CALLDATACOPY:
                var memOffsetData  = program.StackPop();
                var dataOffsetData = program.StackPop();
                var lengthData     = program.StackPop();
                var msgData        = program.GetDataCopy(dataOffsetData, lengthData);
                program.SaveMemory(memOffsetData.GetIntValueSafe(), msgData.ToArray());
                program.Step();
                break;

            case SolidityOpCodes.ADDRESS:
                var address = program.GetOwnerAddress();
                program.StackPush(address);
                program.Step();
                break;

            case SolidityOpCodes.AND:
                var word1 = program.StackPop();
                var word2 = program.StackPop();
                word1.And(word2);
                program.StackPush(word1);
                program.Step();
                break;

            case SolidityOpCodes.OR:
                var w1 = program.StackPop();
                var w2 = program.StackPop();
                w1.Or(w2);
                program.StackPush(w1);
                program.Step();
                break;

            case SolidityOpCodes.XOR:
                var xorW1 = program.StackPop();
                var xorW2 = program.StackPop();
                xorW1.XOR(xorW2);
                program.StackPush(xorW1);
                program.Step();
                break;

            case SolidityOpCodes.BYTE:
                var      bw1    = program.StackPop();
                var      bw2    = program.StackPop();
                DataWord result = new DataWord();
                var      vBw1   = bw1.GetValue();
                if (!bw1.GetValue().Equals(BG_32))
                {
                    byte tmp = bw2.GetData()[bw1.GetInt()];
                    bw2.And(DataWord.ZERO);
                    bw2.GetData()[31] = tmp;
                    result            = bw2;
                }

                program.StackPush(result);
                program.Step();
                break;

            case SolidityOpCodes.ISZERO:
                var isZeroW1 = program.StackPop();
                // var isZeroW1 = stack.Last();
                if (isZeroW1.IsZero())
                {
                    isZeroW1.GetData()[31] = 1;
                }
                else
                {
                    isZeroW1.And(DataWord.ZERO);
                }

                program.StackPush(isZeroW1);
                program.Step();
                break;

            case SolidityOpCodes.EQ:
                var eqW1 = program.StackPop();
                var eqW2 = program.StackPop();
                if (eqW1.XOR(eqW2).IsZero())
                {
                    eqW1.And(DataWord.ZERO);
                    eqW1.GetData()[31] = 1;
                }
                else
                {
                    eqW1.And(DataWord.ZERO);
                }

                program.StackPush(eqW1);
                program.Step();
                break;

            case SolidityOpCodes.GT:
                var gtW1 = program.StackPop();
                var gtW2 = program.StackPop();
                if (gtW1.GetValue().CompareTo(gtW2.GetValue()) == 1)
                {
                    gtW1.And(DataWord.ZERO);
                    gtW1.GetData()[31] = 1;
                }
                else
                {
                    gtW1.And(DataWord.ZERO);
                }

                program.StackPush(gtW1);
                program.Step();
                break;

            case SolidityOpCodes.SGT:
                var sgtW1 = program.StackPop();
                var sgtW2 = program.StackPop();
                if (sgtW1.GetSValue().CompareTo(sgtW2.GetSValue()) == 1)
                {
                    sgtW1.And(DataWord.ZERO);
                    sgtW1.GetData()[31] = 1;
                }
                else
                {
                    sgtW1.And(DataWord.ZERO);
                }

                program.StackPush(sgtW1);
                program.Step();
                break;

            case SolidityOpCodes.LT:
                var ltW1 = program.StackPop();
                var ltW2 = program.StackPop();
                if (ltW1.GetValue().CompareTo(ltW2.GetValue()) == -1)
                {
                    ltW1.And(DataWord.ZERO);
                    ltW1.GetData()[31] = 1;
                }
                else
                {
                    ltW1.And(DataWord.ZERO);
                }

                program.StackPush(ltW1);
                program.Step();
                break;

            case SolidityOpCodes.SLT:
                var sltW1 = program.StackPop();
                var sltW2 = program.StackPop();
                if (sltW1.GetSValue().CompareTo(sltW2.GetSValue()) == -1)
                {
                    sltW1.And(DataWord.ZERO);
                    sltW1.GetData()[31] = 1;
                }
                else
                {
                    sltW1.And(DataWord.ZERO);
                }

                program.StackPush(sltW1);
                program.Step();
                break;

            case SolidityOpCodes.MSTORE:
                var msStoreW1 = program.StackPop();
                var msStoreW2 = program.StackPop();
                program.SaveMemory(msStoreW1, msStoreW2);
                program.Step();
                break;

            case SolidityOpCodes.MSTORE8:
                var    addr    = program.StackPop();
                var    value   = program.StackPop();
                byte[] byteVal = { value.GetData()[31] };
                program.SaveMemory(addr.GetIntValueSafe(), byteVal);
                program.Step();
                break;

            case SolidityOpCodes.CALLVALUE:
                var callValue = program.GetCallValue();
                program.StackPush(callValue);
                program.Step();
                break;

            case SolidityOpCodes.JUMPI:
                var pos  = program.StackPop();
                var cond = program.StackPop();
                if (!cond.IsZero() && !pos.IsZero())
                {
                    int nextPC = program.VerifyJumpDest(pos);
                    program.SetPc(nextPC);
                }
                else
                {
                    program.Step();
                }
                break;

            case SolidityOpCodes.JUMP:
                var jumpW1 = program.StackPop();
                var nextPc = program.VerifyJumpDest(jumpW1);
                program.SetPc(nextPc);
                break;

            case SolidityOpCodes.JUMPDEST:
                program.Step();
                break;

            case SolidityOpCodes.DUP1:
            case SolidityOpCodes.DUP2:
            case SolidityOpCodes.DUP3:
            case SolidityOpCodes.DUP4:
            case SolidityOpCodes.DUP5:
            case SolidityOpCodes.DUP6:
            case SolidityOpCodes.DUP7:
            case SolidityOpCodes.DUP8:
            case SolidityOpCodes.DUP9:
            case SolidityOpCodes.DUP10:
            case SolidityOpCodes.DUP11:
            case SolidityOpCodes.DUP12:
            case SolidityOpCodes.DUP13:
            case SolidityOpCodes.DUP14:
            case SolidityOpCodes.DUP15:
            case SolidityOpCodes.DUP16:
                var n      = SizeSolidityCodes[opCode.Value] - SizeSolidityCodes[SolidityOpCodes.DUP1] + 1;
                var dup1W1 = stack[stack.Count() - n];
                program.StackPush(dup1W1);
                program.Step();
                break;

            case SolidityOpCodes.CODECOPY:
                byte[] fullCode = ByteUtil.EMPTY_BYTE_ARRAY;
                fullCode = program.GetCode().ToArray();
                int copyDataW1     = program.StackPop().GetIntValueSafe();
                int copyDataW2     = program.StackPop().GetIntValueSafe();
                int copyDataW3     = program.StackPop().GetIntValueSafe();
                int sizeToBeCopied =
                    (long)copyDataW2 + copyDataW3 > fullCode.Length ?
                    (fullCode.Length < copyDataW2 ? 0 : fullCode.Length - copyDataW2)
                                    : copyDataW3;
                byte[] codeCopy = new byte[copyDataW3];
                if (copyDataW2 < fullCode.Length)
                {
                    Array.Copy(fullCode, copyDataW2, codeCopy, 0, sizeToBeCopied);
                }
                program.SaveMemory(copyDataW1, codeCopy);
                program.Step();
                break;

            case SolidityOpCodes.RETURN:
            case SolidityOpCodes.REVERT:
                int    retW1   = program.StackPop().GetIntValueSafe();
                int    retW2   = program.StackPop().GetIntValueSafe();
                byte[] hReturn = program.ChunkMemory(retW1, retW2);
                program.SetHReturn(hReturn);
                program.Step();
                program.Stop();
                if (opCode == SolidityOpCodes.REVERT)
                {
                    program.GetResult().SetRevert();
                }
                break;

            case SolidityOpCodes.SWAP1:
            case SolidityOpCodes.SWAP2:
            case SolidityOpCodes.SWAP3:
            case SolidityOpCodes.SWAP4:
            case SolidityOpCodes.SWAP5:
            case SolidityOpCodes.SWAP6:
            case SolidityOpCodes.SWAP7:
            case SolidityOpCodes.SWAP8:
            case SolidityOpCodes.SWAP9:
            case SolidityOpCodes.SWAP10:
            case SolidityOpCodes.SWAP11:
            case SolidityOpCodes.SWAP12:
            case SolidityOpCodes.SWAP13:
            case SolidityOpCodes.SWAP14:
            case SolidityOpCodes.SWAP15:
            case SolidityOpCodes.SWAP16:
                var sn = SizeSolidityCodes[opCode.Value] - SizeSolidityCodes[SolidityOpCodes.SWAP1] + 2;
                stack.Swap(stack.Count() - 1, stack.Count() - sn);
                program.Step();
                break;

            case SolidityOpCodes.DIV:
                var dW1 = program.StackPop();
                var dW2 = program.StackPop();
                dW1.Div(dW2);
                program.StackPush(dW1);
                program.Step();
                break;

            case SolidityOpCodes.POP:
                program.StackPop();
                program.Step();
                break;

            case SolidityOpCodes.MLOAD:
                var mloadW1  = program.StackPop();
                var memoryW2 = program.LoadMemory(mloadW1);
                program.StackPush(memoryW2);
                program.Step();
                break;

            case SolidityOpCodes.ADD:
                var addW1 = program.StackPop();
                var addW2 = program.StackPop();
                addW1.Add(addW2);
                program.StackPush(addW1);
                program.Step();
                break;

            case SolidityOpCodes.SUB:
                var subW1 = program.StackPop();
                var subW2 = program.StackPop();
                subW1.Sub(subW2);
                program.StackPush(subW1);
                program.Step();
                break;

            case SolidityOpCodes.MUL:
                var mulW1 = program.StackPop();
                var mulW2 = program.StackPop();
                mulW1.Mul(mulW2);
                program.StackPush(mulW1);
                program.Step();
                break;

            case SolidityOpCodes.CALL:     // CONTINUE TO DEVELOP METHOD CALL.
                program.StackPop();
                var codeAddress = program.StackPop();
                var cv          = program.StackPop();

                DataWord inDataOffs  = program.StackPop();
                DataWord inDataSize  = program.StackPop();
                DataWord outDataOffs = program.StackPop();
                DataWord outDataSize = program.StackPop();

                program.MemoryExpand(outDataOffs, outDataSize);
                var msg      = new SolidityMessageCall(opCode.Value, null, codeAddress, cv, inDataOffs, inDataSize, outDataOffs, outDataSize);
                var contract = SolidityPrecompiledContract.GetContractForAddress(codeAddress);

                if (contract != null)
                {
                    program.CallPrecompiledAddress(msg, contract);
                }

                program.Step();
                break;

            case SolidityOpCodes.NOT:
                var notW1 = program.StackPop();
                notW1.BNot();
                program.StackPush(notW1);
                program.Step();
                break;

            case SolidityOpCodes.EXP:
                var expWord1 = program.StackPop();
                var expWord2 = program.StackPop();
                expWord1.Exp(expWord2);
                program.StackPush(expWord1);
                program.Step();
                break;

            case SolidityOpCodes.CALLDATASIZE:
                var dataSize = program.GetDataSize();
                program.StackPush(dataSize);
                program.Step();
                break;

            case SolidityOpCodes.SSTORE:
                var sstoreWord1 = program.StackPop();
                var sstoreWord2 = program.StackPop();
                var tt          = sstoreWord1.GetData().ToHexString();
                var tt2         = sstoreWord2.GetData().ToHexString();
                program.SaveStorage(sstoreWord1, sstoreWord2);
                program.Step();
                break;

            case SolidityOpCodes.STOP:
                program.SetHReturn(SolidityMemory.EMPTY_BYTE_ARRAY);
                program.Stop();
                break;

            case SolidityOpCodes.SLOAD:
                var sLoadKey = program.StackPop();
                var sLoadVal = program.StorageLoad(sLoadKey);
                program.StackPush(sLoadVal); program.Step();
                break;

            case SolidityOpCodes.SHA3:
                var    sha3MemOffsetData = program.StackPop();
                var    sha3LengthData    = program.StackPop();
                byte[] buffer            = program.ChunkMemory(sha3MemOffsetData.GetIntValueSafe(), sha3LengthData.GetIntValueSafe());
                var    hash    = HashFactory.Crypto.SHA3.CreateBlake256();
                var    shaWord = hash.ComputeBytes(buffer).GetBytes();
                program.StackPush(shaWord);
                program.Step();
                break;

            case SolidityOpCodes.MSIZE:
                int memSize = program.GetMemorySize();
                var sizeW   = new DataWord(memSize);
                program.StackPush(sizeW);
                program.Step();
                break;

            case SolidityOpCodes.LOG0:
            case SolidityOpCodes.LOG1:
            case SolidityOpCodes.LOG2:
            case SolidityOpCodes.LOG3:
            case SolidityOpCodes.LOG4:
                var logAdr       = program.GetOwnerAddress();
                var logMemStart  = stack.Pop();
                var logMemOffset = stack.Pop();
                var nTopics      = SizeSolidityCodes[opCode.Value] - SizeSolidityCodes[SolidityOpCodes.LOG0];
                var topics       = new List <DataWord>();
                for (int i = 0; i < nTopics; ++i)
                {
                    DataWord topic = stack.Pop();
                    topics.Add(topic);
                }

                var logData = program.ChunkMemory(logMemStart.GetIntValueSafe(), logMemOffset.GetIntValueSafe());
                program.GetResult().AddLogInfo(new SolidityLogInfo(topics, logData));
                program.Step();
                break;
            }
        }
        public DataWord StorageLoad(DataWord keyWord)
        {
            var scAddr = _progInvoke.GetSmartContractAddress();

            return(_progInvoke.GetStorage().GetStorageRow(scAddr, keyWord));
        }