Skip to content

Commit

Permalink
Evm - Fixes and Wallet forward tests
Browse files Browse the repository at this point in the history
Forward tests: Validating create2, delegateCall, staticCall, transferEther in a contract, storage of created contracts, balances transfers, logs..
  • Loading branch information
juanfranblanco committed Oct 27, 2022
1 parent f67b5e6 commit 2e7c254
Show file tree
Hide file tree
Showing 13 changed files with 1,844 additions and 28 deletions.
6 changes: 6 additions & 0 deletions src/Nethereum.Contracts/Extensions/EventExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,12 @@ public static List<EventLog<TEventDTO>> DecodeAllEvents<TEventDTO>(this FilterLo
return DecodeAllEvents<TEventDTO>(eventABI, logs);
}

public static List<EventLog<TEventDTO>> DecodeAllEvents<TEventDTO>(this List<FilterLog> logs) where TEventDTO : new()
{
var eventABI = ABITypedRegistry.GetEvent<TEventDTO>();
return DecodeAllEvents<TEventDTO>(eventABI, logs.ToArray());
}

public static List<EventLog<TEventDTO>> DecodeAllEvents<TEventDTO>(this TransactionReceipt transactionReceipt) where TEventDTO : new()
{
return transactionReceipt.Logs.DecodeAllEvents<TEventDTO>();
Expand Down
4 changes: 4 additions & 0 deletions src/Nethereum.EVM/ProgramInstructionsUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ public static List<ProgramInstruction> GetProgramInstructions(byte[] byteCodeArr
var opcode = (Instruction)byteCodeArray[i];
var dataLength = currentByte - 0x60 + 1;
var dataBytes = new byte[dataLength];
if(i + dataLength > byteCodeArray.Length)
{
dataLength = byteCodeArray.Length - i -1;
}
for (int x = 0; x < dataLength; x++)
{
dataBytes[x] = byteCodeArray[i + x + 1];
Expand Down
79 changes: 51 additions & 28 deletions src/Nethereum.EVM/ProgramStepExecutionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Nethereum.Hex.HexTypes;
using Newtonsoft.Json.Linq;
using Nethereum.RPC.Eth.Transactions;
using Nethereum.RPC.Eth.Blocks;

namespace Nethereum.EVM
{
Expand All @@ -38,7 +39,9 @@ public static void WriteToMemory(this Program program, int index, byte[] data)

public static void WriteToMemory(this Program program, int index, int totalSize, byte[] data)
{
if (totalSize == 0) return;
//totalSize might be bigger than data length so memory will be extended to match

if(data == null) data = new byte[0];
int newSize = index + totalSize;

Expand Down Expand Up @@ -159,7 +162,6 @@ private static async Task<List<ProgramTrace>> CreateContractAsync(Program progra
program.Stop();
}

program.Step();
return trace;
}

Expand Down Expand Up @@ -234,7 +236,13 @@ private static async Task<List<ProgramTrace>> GenericCallAsync(Program program,
var resultMemoryDataIndex = (int)program.StackPopAndConvertToBigInteger();
var resultMemoryDataLength = (int)program.StackPopAndConvertToBigInteger();

var dataInput = program.Memory.GetRange(dataInputIndex, dataInputLength).ToArray();
var dataInput = new byte[] { };
if (dataInputLength != 0)
{
dataInput = program.Memory.GetRange(dataInputIndex, dataInputLength).ToArray();
}


var callInput = new CallInput()
{
From = from,
Expand All @@ -247,30 +255,39 @@ private static async Task<List<ProgramTrace>> GenericCallAsync(Program program,
program.ProgramContext.ExecutionStateService.UpsertInternalBalance(program.ProgramContext.AddressContract, -value);

var byteCode = await program.ProgramContext.ExecutionStateService.GetCodeAsync(codeAddress.ConvertToEthereumChecksumAddress());

var programContext = new ProgramContext(callInput, program.ProgramContext.ExecutionStateService, program.ProgramContext.AddressCaller,
(long)program.ProgramContext.BlockNumber, (long)program.ProgramContext.Timestamp, program.ProgramContext.Coinbase, (long)program.ProgramContext.BaseFee);
var callProgram = new Program(byteCode, programContext);
var vm = new EVMSimulator();
var trace = await vm.ExecuteAsync(callProgram, vmExecutionStep, traceEnabled);

if (callProgram.ProgramResult.IsRevert == false)
if (byteCode.Length == 0) // calling / transfering a non contract account
{
program.ProgramContext.ExecutionStateService.UpsertInternalBalance(to, value);
program.StackPush(1);
var result = callProgram.ProgramResult.Result;
program.ProgramResult.Result = callProgram.ProgramResult.Result;
WriteToMemory(program, resultMemoryDataIndex, resultMemoryDataLength, result);
program.ProgramResult.Logs.AddRange(callProgram.ProgramResult.Logs);
program.ProgramResult.InnerCalls.Add(callInput);
program.ProgramResult.InnerCalls.AddRange(callProgram.ProgramResult.InnerCalls);
program.Step();
return new List<ProgramTrace>();
}
else
{
program.Stop();
}
var programContext = new ProgramContext(callInput, program.ProgramContext.ExecutionStateService, program.ProgramContext.AddressCaller,
(long)program.ProgramContext.BlockNumber, (long)program.ProgramContext.Timestamp, program.ProgramContext.Coinbase, (long)program.ProgramContext.BaseFee);
var callProgram = new Program(byteCode, programContext);
var vm = new EVMSimulator();
var trace = await vm.ExecuteAsync(callProgram, vmExecutionStep, traceEnabled);

return trace;
if (callProgram.ProgramResult.IsRevert == false)
{
program.StackPush(1);
var result = callProgram.ProgramResult.Result;
program.ProgramResult.Result = callProgram.ProgramResult.Result;
WriteToMemory(program, resultMemoryDataIndex, resultMemoryDataLength, result);
program.ProgramResult.Logs.AddRange(callProgram.ProgramResult.Logs);
program.ProgramResult.InnerCalls.Add(callInput);
program.ProgramResult.InnerCalls.AddRange(callProgram.ProgramResult.InnerCalls);
program.Step();
}
else
{
program.Stop();
}
return trace;
}

}

public static async Task BalanceAsync(this Program program)
Expand Down Expand Up @@ -388,19 +405,25 @@ public static void ReturnDataCopy(this Program program)
var resultIndex = (int)program.StackPopAndConvertToBigInteger();
var lengthResult = (int)program.StackPopAndConvertToBigInteger();
var result = program.ProgramResult.Result;
if (result == null) throw new Exception("No result data");

var size = result.Length - resultIndex;

if (lengthResult < size)
if (result == null)
{
size = lengthResult;
program.WriteToMemory(memoryIndex, lengthResult, new byte[] { });
}
else
{

var size = result.Length - resultIndex;

if (lengthResult < size)
{
size = lengthResult;
}

var dataToCopy = new byte[size];
Array.Copy(result, resultIndex, dataToCopy, 0, size);
var dataToCopy = new byte[size];
Array.Copy(result, resultIndex, dataToCopy, 0, size);

program.WriteToMemory(memoryIndex, lengthResult, dataToCopy);
program.WriteToMemory(memoryIndex, lengthResult, dataToCopy);
}
program.Step();
}

Expand Down

0 comments on commit 2e7c254

Please sign in to comment.