Skip to content

Commit

Permalink
Mud further refactoring, deployment, system management and registrati…
Browse files Browse the repository at this point in the history
…on, table registration, test fixed mostly
  • Loading branch information
juanfranblanco committed May 15, 2024
1 parent 8c493f4 commit 24546cd
Show file tree
Hide file tree
Showing 59 changed files with 1,040 additions and 388 deletions.
16 changes: 13 additions & 3 deletions src/Nethereum.ABI/FunctionEncoding/ByteCodeLibrary.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Nethereum.Util;
using System.IO;
namespace Nethereum.ABI.FunctionEncoding
{
public class ByteCodeLibrary
Expand All @@ -12,12 +13,21 @@ public class ByteCodeLibrary
/// <returns></returns>
public static ByteCodeLibrary CreateFromPath(string path, string libraryName, string libraryAddress)
{
path = path.Replace("\\", "/");
var placeHolderKey = Sha3Keccack.Current.CalculateHash(path + ":" + libraryName).Substring(0, 34);
return new ByteCodeLibrary() { PlaceholderKey = placeHolderKey, Address = libraryAddress };
var library = new ByteCodeLibrary() { Address = libraryAddress, Path = path, LibraryName = libraryName };
library.CalculatePlaceHolderKey();
return library;
}

public string PlaceholderKey { get; set; }
public string Address { get; set; }
public string LibraryName { get; set; }
public string Path { get; set; }
public string ByteCode { get; set; }

public void CalculatePlaceHolderKey()
{
var path = Path.Replace("\\", "/");
PlaceholderKey = Sha3Keccack.Current.CalculateHash(path + ":" + LibraryName).Substring(0, 34);
}
}
}
3 changes: 2 additions & 1 deletion src/Nethereum.ABI/FunctionEncoding/ByteCodeLibraryLinker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ private static string CreatePlaceholder(string key)
return ByteCodeConstants.LIBRARY_PLACEHOLDER_PREFIX + key + ByteCodeConstants.LIBRARY_PLACEHOLDER_SUFFIX;
}

public string LinkByteCode(string byteCode, params ByteCodeLibrary[] byteCodeLibraries)
public static string LinkByteCode(string byteCode, params ByteCodeLibrary[] byteCodeLibraries)
{
if(byteCodeLibraries == null || byteCodeLibraries.Length == 0) return byteCode;
foreach (var byteCodeLibrary in byteCodeLibraries)
{
var placeholder = CreatePlaceholder(byteCodeLibrary.PlaceholderKey);
Expand Down
2 changes: 1 addition & 1 deletion src/Nethereum.Contracts/ContractDeploymentMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public ContractDeploymentMessage(string byteCode)
/// <summary>
/// ByteCode (Compiled code) used for deployment
/// </summary>
public string ByteCode { get; internal set; }
public string ByteCode { get; set; }

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ public static BigInteger CalculateVForChainId(BigInteger chainId)

public static byte[] CalculateVForChainIdAsBytes(BigInteger chainId)
{
return CalculateVForChainId(chainId).ToBytesForRLPEncoding();
return CalculateVForChainId(chainId).ToBytesForRLPEncoding();
}
public static readonly byte[] DefaultR = "2222222222222222222222222222222222222222222222222222222222222222".HexToByteArray();
public static readonly byte[] DefaultS = "2222222222222222222222222222222222222222222222222222222222222222".HexToByteArray();

public const string ByteCode = "604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3";
public const string RuntimeByteCode = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3";
public string RawTransaction { get; set; }
Expand All @@ -70,4 +70,18 @@ public static Create2DeterministicDeploymentProxyDeployment GetDefaultNoneEIP155
};
}
}

public class Create2ContractDeploymentTransactionResult
{
public bool AlreadyDeployed { get; set; }
public string TransactionHash { get; set; }
public string Address { get; set; }
}

public class Create2ContractDeploymentTransactionReceiptResult
{
public bool AlreadyDeployed { get; set; }
public string Address { get; set; }
public TransactionReceipt TransactionReceipt { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
using Nethereum.Contracts.MessageEncodingServices;

using System.Diagnostics;
using Nethereum.ABI.FunctionEncoding;
using System.Threading;

namespace Nethereum.Contracts.Create2Deployment
{
Expand Down Expand Up @@ -140,14 +142,8 @@ public async Task<string> DeployProxyAndGetContractAddressAsync(Create2Determini
if (await HasProxyBeenDeployedAsync(deployment.Address)) return deployment.Address;

await ValidateAndSendEnoughBalanceForProxyDeploymentAndWaitForReceiptAsync(deployment);
var currentLegacySetting = _ethApiContractService.TransactionManager.UseLegacyAsDefault;

_ethApiContractService.TransactionManager.UseLegacyAsDefault = true;

var txn = await _ethApiContractService.Transactions.SendRawTransaction.SendRequestAsync(deployment.RawTransaction);

_ethApiContractService.TransactionManager.UseLegacyAsDefault = currentLegacySetting;

var receipt = await _ethApiContractService.TransactionManager.TransactionReceiptService.PollForReceiptAsync(txn);
var deployed = await HasProxyBeenDeployedAsync(deployment.Address);
if(!deployed) throw new Exception("Proxy not deployed");
Expand All @@ -172,49 +168,57 @@ public async Task ValidateAndSendEnoughBalanceForProxyDeploymentAndWaitForReceip
}
}

public string CalculateCreate2Address<TDeploymentMessage>(TDeploymentMessage deploymentMessage, string deployerProxyAddress, string salt) where TDeploymentMessage : ContractDeploymentMessage
public string CalculateCreate2Address<TDeploymentMessage>(TDeploymentMessage deploymentMessage, string deployerProxyAddress, string salt, params ByteCodeLibrary[] byteCodeLibraries) where TDeploymentMessage : ContractDeploymentMessage, new()
{
var deploymentEncodingService = new DeploymentMessageEncodingService<TDeploymentMessage>();
var deploymentData = deploymentEncodingService.GetDeploymentData(deploymentMessage);
return deploymentMessage.CalculateCreate2Address(deployerProxyAddress, salt, byteCodeLibraries);
}

return CalculateCreate2Address(deployerProxyAddress, salt, deploymentData);
public string CalculateCreate2Address<TDeploymentMessage>(TDeploymentMessage deploymentMessage, string deployerProxyAddress, string salt) where TDeploymentMessage : ContractDeploymentMessage, new()
{
return deploymentMessage.CalculateCreate2Address(deployerProxyAddress, salt);
}

public string CalculateCreate2Address(string deployerProxyAddress, string salt, string contractByteCode)
{
return ContractUtils.CalculateCreate2Address(deployerProxyAddress, salt, contractByteCode);
}

public async Task<bool> CheckContractAlreadyDeployedAsync(string deployerProxyAddress, string salt, string contractByteCode)
public async Task<bool> HasContractAlreadyDeployedAsync(string deployerProxyAddress, string salt, string contractByteCode)
{
var create2Address = CalculateCreate2Address(deployerProxyAddress, salt, contractByteCode);
var code = await _ethApiContractService.GetCode.SendRequestAsync(create2Address);
return !string.IsNullOrEmpty(code?.RemoveHexPrefix());
}

public async Task<bool> CheckContractAlreadyDeployedAsync<TDeploymentMessage>(TDeploymentMessage deploymentMessage, string deployerProxyAddress, string salt)
where TDeploymentMessage : ContractDeploymentMessage
public async Task<bool> HasContractAlreadyDeployedAsync<TDeploymentMessage>(TDeploymentMessage deploymentMessage, string deployerProxyAddress, string salt)
where TDeploymentMessage : ContractDeploymentMessage, new()
{
var create2Address = CalculateCreate2Address(deploymentMessage, deployerProxyAddress, salt);
var code = await _ethApiContractService.GetCode.SendRequestAsync(create2Address);
return !string.IsNullOrEmpty(code?.RemoveHexPrefix());
}

public async Task<bool> CheckContractAlreadyDeployedAsync(string address)
public async Task<bool> HasContractAlreadyDeployedAsync(string address)
{
var code = await _ethApiContractService.GetCode.SendRequestAsync(address);
return !string.IsNullOrEmpty(code?.RemoveHexPrefix());
}

public async Task<string> DeployContractRequestAsync<TDeploymentMessage>(TDeploymentMessage deploymentMessage, string deployerProxyAddress, string salt)
where TDeploymentMessage : ContractDeploymentMessage
public async Task<Create2ContractDeploymentTransactionResult> DeployContractRequestAsync<TDeploymentMessage>(TDeploymentMessage deploymentMessage, string deployerProxyAddress, string salt, params ByteCodeLibrary[] byteCodeLibraries)
where TDeploymentMessage : ContractDeploymentMessage, new()
{
if (await CheckContractAlreadyDeployedAsync(deploymentMessage, deployerProxyAddress, salt))
throw new Exception("Contract already deployed");
var address = CalculateCreate2Address(deploymentMessage, deployerProxyAddress, salt, byteCodeLibraries);
if (await HasContractAlreadyDeployedAsync(address))
{
return new Create2ContractDeploymentTransactionResult()
{
Address = address,
AlreadyDeployed = true
};
}

var deploymentEncodingService = new DeploymentMessageEncodingService<TDeploymentMessage>();
var deploymentData = deploymentEncodingService.GetDeploymentData(deploymentMessage);

var deploymentData = deploymentEncodingService.GetDeploymentData(deploymentMessage, byteCodeLibraries);

var transactionInput = new TransactionInput()
{
Expand All @@ -225,44 +229,88 @@ public async Task<string> DeployContractRequestAsync<TDeploymentMessage>(TDeploy

var gas = await _ethApiContractService.Transactions.EstimateGas.SendRequestAsync(transactionInput);
transactionInput.Gas = gas;
return await _ethApiContractService.TransactionManager.SendTransactionAsync(transactionInput);
var txnHash = await _ethApiContractService.TransactionManager.SendTransactionAsync(transactionInput);
return new Create2ContractDeploymentTransactionResult()
{
TransactionHash = txnHash,
Address = address
};
}

public async Task<TransactionReceipt> DeployContractRequestAndWaitForReceiptAsync<TDeploymentMessage>(TDeploymentMessage deploymentMessage, string deployerProxyAddress, string salt)
where TDeploymentMessage : ContractDeploymentMessage
public async Task<Create2ContractDeploymentTransactionReceiptResult> DeployContractRequestAndWaitForReceiptAsync<TDeploymentMessage>(TDeploymentMessage deploymentMessage, string deployerProxyAddress, string salt, ByteCodeLibrary[] byteCodeLibraries = null, CancellationToken cancellationToken = default)
where TDeploymentMessage : ContractDeploymentMessage, new()
{
var txnHash = await DeployContractRequestAsync(deploymentMessage, deployerProxyAddress, salt);
var receipt = await _ethApiContractService.TransactionManager.TransactionReceiptService.PollForReceiptAsync(txnHash);
if (await CheckContractAlreadyDeployedAsync(deploymentMessage, deployerProxyAddress, salt))
var deploymentTransactionResult = await DeployContractRequestAsync(deploymentMessage, deployerProxyAddress, salt, byteCodeLibraries);
if (deploymentTransactionResult.AlreadyDeployed)
{
return new Create2ContractDeploymentTransactionReceiptResult()
{
Address = deploymentTransactionResult.Address,
AlreadyDeployed = true
};
}
var receipt = await _ethApiContractService.TransactionManager.TransactionReceiptService.PollForReceiptAsync(deploymentTransactionResult.TransactionHash,cancellationToken);
if (await HasContractAlreadyDeployedAsync(deploymentTransactionResult.Address))
{
return receipt;
return new Create2ContractDeploymentTransactionReceiptResult()
{
Address = deploymentTransactionResult.Address,
TransactionReceipt = receipt
};
}
throw new Exception("Contract not deployed");
}

public async Task<string> DeployContractRequestAsync(string deployerProxyAddress, string salt, string contractByteCode)
public async Task<Create2ContractDeploymentTransactionResult> DeployContractRequestAsync(string deployerProxyAddress, string salt, string contractByteCode)
{
if (await CheckContractAlreadyDeployedAsync(deployerProxyAddress, salt, contractByteCode))
throw new Exception("Contract already deployed");
var transactionInput = new TransactionInput()
var address = ContractUtils.CalculateCreate2Address(deployerProxyAddress, salt, contractByteCode);
if (await HasContractAlreadyDeployedAsync(address))
{
From = _ethApiContractService.TransactionManager.Account.Address,
Data = salt.EnsureHexPrefix() + contractByteCode.RemoveHexPrefix(),
To = deployerProxyAddress
};
return new Create2ContractDeploymentTransactionResult()
{
Address = address,
AlreadyDeployed = true
};
}
else
{
var transactionInput = new TransactionInput()
{
From = _ethApiContractService.TransactionManager.Account.Address,
Data = salt.EnsureHexPrefix() + contractByteCode.RemoveHexPrefix(),
To = deployerProxyAddress
};

var gas = await _ethApiContractService.Transactions.EstimateGas.SendRequestAsync(transactionInput);
transactionInput.Gas = gas;
return await _ethApiContractService.TransactionManager.SendTransactionAsync(transactionInput);
var gas = await _ethApiContractService.Transactions.EstimateGas.SendRequestAsync(transactionInput);
transactionInput.Gas = gas;
var txnHash = await _ethApiContractService.TransactionManager.SendTransactionAsync(transactionInput);
return new Create2ContractDeploymentTransactionResult()
{
TransactionHash = txnHash,
Address = address
};
}
}

public async Task<TransactionReceipt> DeployContractRequestAndWaitForReceiptAsync(string deployerProxyAddress, string salt, string contractByteCode)
public async Task<Create2ContractDeploymentTransactionReceiptResult> DeployContractRequestAndWaitForReceiptAsync(string deployerProxyAddress, string salt, string contractByteCode, CancellationToken cancellationToken = default)
{
var txnHash = await DeployContractRequestAsync(deployerProxyAddress, salt, contractByteCode);
var receipt = await _ethApiContractService.TransactionManager.TransactionReceiptService.PollForReceiptAsync(txnHash);
if (await CheckContractAlreadyDeployedAsync(deployerProxyAddress, salt, contractByteCode))
var deploymentTransactionResult = await DeployContractRequestAsync(deployerProxyAddress, salt, contractByteCode);
if (deploymentTransactionResult.AlreadyDeployed)
{
return new Create2ContractDeploymentTransactionReceiptResult()
{
Address = deploymentTransactionResult.Address,
AlreadyDeployed = true
};
}
var receipt = await _ethApiContractService.TransactionManager.TransactionReceiptService.PollForReceiptAsync(deploymentTransactionResult.TransactionHash, cancellationToken);
if (await HasContractAlreadyDeployedAsync(deploymentTransactionResult.Address))
{
return receipt;
return new Create2ContractDeploymentTransactionReceiptResult()
{
Address = deploymentTransactionResult.Address,
TransactionReceipt = receipt
};
}
throw new Exception("Contract not deployed");
}
Expand Down

0 comments on commit 24546cd

Please sign in to comment.