-
Notifications
You must be signed in to change notification settings - Fork 6
Open
Description
@Enigmatic331
These are some thoughts for a generic service, with some small refactoring of your implementation.
The main idea is to:
- Have a generic interface that all Delegated signed functions have to adhere.
Parameter attributes cannot be put here (or create a base class) as we don't know how many extra parameters we will have. Another option will be to use a struct matching the message if using Solidity V2 in future versions, which will be far much easier when doing mappings
public interface IDelegatedSignedFunction
{
string Owner { get; set; }
BigInteger Fee { get; set; }
BigInteger DelegatedNonce { get; set; }
byte[] Sig { get; set; }
string FeeAccount { get; set; }
}Then a generic service can be put in place as follows.
public partial class SignedTransferFunction : SignedTransferFunctionBase { }
[Function("signedTransfer", "bool")]
public class SignedTransferFunctionBase : FunctionMessage
{
[Parameter("address", "tokenOwner", 1)]
public virtual string Owner { get; set; }
[Parameter("address", "to", 2)]
public virtual string To { get; set; }
[Parameter("uint256", "tokens", 3)]
public virtual BigInteger Tokens { get; set; }
[Parameter("uint256", "fee", 4)]
public virtual BigInteger Fee { get; set; }
[Parameter("uint256", "nonce", 5)]
public virtual BigInteger DelegatedNonce { get; set; }
[Parameter("bytes", "sig", 6)]
public virtual byte[] Sig { get; set; }
[Parameter("address", "feeAccount", 7)]
public virtual string FeeAccount { get; set; }
}
//my custom partial implementing IDelegatedSignedFunction
public partial class SignedTransferFunction : SignedTransferFunctionBase, IDelegatedSignedFunction
{
}
public partial class TransferFunction : TransferFunctionBase { }
[Function("transfer", "bool")]
public class TransferFunctionBase : FunctionMessage
{
[Parameter("address", "_to", 1)]
public virtual string To { get; set; }
[Parameter("uint256", "_value", 2)]
public virtual BigInteger Value { get; set; }
}
public interface IDelegatedSignedFunction
{
string Owner { get; set; }
BigInteger Fee { get; set; }
BigInteger DelegatedNonce { get; set; }
byte[] Sig { get; set; }
string FeeAccount { get; set; }
}
public class TokenDelegatedSignerService : DelegatedSignerService<TransferFunction, SignedTransferFunction>
{
public override SignedTransferFunction MapDelegatedFunctionToSignedFunction(TransferFunction delegatedFunction,
SignedTransferFunction delegatedSignedFunction)
{
delegatedSignedFunction.To = delegatedFunction.To;
delegatedSignedFunction.Tokens = delegatedFunction.Value;
return delegatedSignedFunction;
}
public override TransferFunction MapSignedFunctionToDelegatedSignedFunction(TransferFunction delegatedFunction,
SignedTransferFunction delegatedSignedFunction)
{
delegatedFunction.To = delegatedSignedFunction.To;
delegatedFunction.Value = delegatedSignedFunction.Tokens;
return delegatedFunction;
}
}
public abstract class DelegatedSignerService<TDelegatedFunction, TDelegatedSignedFunction> where TDelegatedFunction: FunctionMessage, new()
where TDelegatedSignedFunction: FunctionMessage, IDelegatedSignedFunction, new()
{
public string ContractAddress { get; set; }
public string GetDelegatedFunctionSignature()
{
return ABITypedRegistry.GetFunctionABI<TDelegatedFunction>().Sha3Signature;
}
public string GetHashToSign(TDelegatedFunction delegatedFunction, string owner, BigInteger nonce, BigInteger fee)
{
var abiEncode = new ABIEncode();
return Sha3Keccack.Current.CalculateHashFromHex(
GetDelegatedFunctionSignature(),
abiEncode.GetABIEncodedPacked("address", ContractAddress).ToHex(),
abiEncode.GetABIEncodedPacked("address", owner).ToHex(),
delegatedFunction.GetParamsEncodedPacked().ToHex(),
abiEncode.GetABIEncodedPacked("uint256", nonce).ToHex(),
abiEncode.GetABIEncodedPacked("uint256", fee).ToHex()
);
}
public byte[] GetSignature(TDelegatedFunction delegatedFunction, BigInteger delegatedNonce, BigInteger fee, string privateKey)
{
var ethEcKey = new EthECKey(privateKey);
var messageSigner = new Nethereum.Signer.EthereumMessageSigner();
return messageSigner.Sign(GetHashToSign(delegatedFunction, ethEcKey.GetPublicAddress(), delegatedNonce, fee).HexToByteArray(), ethEcKey).HexToByteArray();
}
public TDelegatedSignedFunction GetSignedRequest(TDelegatedFunction delegatedFunction, BigInteger delegatedNonce, BigInteger fee, string feeAccount,
string privateKey)
{
var signedFunction = new TDelegatedSignedFunction();
signedFunction = MapDelegatedFunctionToSignedFunction(delegatedFunction, signedFunction);
signedFunction.Fee = fee;
signedFunction.DelegatedNonce = delegatedNonce;
signedFunction.FeeAccount = feeAccount;
signedFunction.Sig = GetSignature(delegatedFunction, delegatedNonce, fee, privateKey);
return signedFunction;
}
public TDelegatedSignedFunction GetSignedRequest(TDelegatedSignedFunction delegatedSignedFunctionToBeSigned,
string privateKey)
{
var delegatedFunction =
MapSignedFunctionToDelegatedSignedFunction(new TDelegatedFunction(), delegatedSignedFunctionToBeSigned);
delegatedSignedFunctionToBeSigned.Sig = GetSignature(delegatedFunction, delegatedSignedFunctionToBeSigned.DelegatedNonce, delegatedSignedFunctionToBeSigned.Fee, privateKey);
return delegatedSignedFunctionToBeSigned;
}
public abstract TDelegatedSignedFunction MapDelegatedFunctionToSignedFunction(
TDelegatedFunction delegatedFunction, TDelegatedSignedFunction delegatedSignedFunction);
public abstract TDelegatedFunction MapSignedFunctionToDelegatedSignedFunction(
TDelegatedFunction delegatedFunction, TDelegatedSignedFunction delegatedSignedFunction);
}Enigmatic331
Metadata
Metadata
Assignees
Labels
No labels