Skip to content

Usage Examples

Billy Cropley edited this page Oct 15, 2018 · 1 revision

Performing ECSign, ECRecover, message signing

// Create a personal message hash the same way as eth_sign (using the "\x19Ethereum Signed Message:\n" prefix).
byte[] messageHash = SolidityUtil.HashPersonalMessage("hello world");

var privateKey = "0x150a5bb56e818a0a59cb327a0d92a799a06c1b850b04d4f355d712ec89a31b75";

// Sign the message and returns the signature object parts (byte[] R, byte[] S, byte V).
var signature = SolidityUtil.ECSign(messageHash, privateKey);

// Recover the public key from the message and signature.
var recoveredPublicKey = SolidityUtil.ECRecover(messageHash, signature);

// Get the account Address of the public key.
var recoveredAddress = SolidityUtil.PublicKeyToAddress(recoveredPublicKey);

// Test that recovered address matches the private key.
Assert.Equal(SolidityUtil.PrivateKeyToAddress(privateKey), recoveredAddress);

EC signature format conversions

byte[] messageHash = SolidityUtil.HashPersonalMessage("hello world");
var privateKey = "0x150a5bb56e818a0a59cb327a0d92a799a06c1b850b04d4f355d712ec89a31b75";
var signature = SolidityUtil.ECSign(messageHash, privateKey);

// Convert signature object into the serialized byte array format:
var signatureSerialized = SolidityUtil.SignatureToRpcFormat(signature);

// Convert the serialized signature back into the signature parts:
var signatureObject = SolidityUtil.SignatureFromRpcFormat(signatureSerialized);

ABI encoding and non-standard tight packing

// Some example values
var contractNonce = 123;
var contractAddress = "0x7cafb9c3de0fd02142754ce648ba7db04e4c161e";
var amount = 395895647;

// Regular ABI encoding of values.
var encodedValues = SolidityUtil.AbiEncode(
    (SolidityType.UInt256, contractNonce),
    (SolidityType.Address, contractAddress),
    (SolidityType.UInt256, amount));

// Tightly packed ABI encoding of values.
var packedValues = SolidityUtil.AbiPack(
    (SolidityType.UInt256, contractNonce),
    (SolidityType.Address, contractAddress),
    (SolidityType.UInt256, amount));

// Tightly pack and hash ABI values.
var packedValuesHash = SolidityUtil.PackAndHash(
    (SolidityType.UInt256, contractNonce),
    (SolidityType.Address, contractAddress),
    (SolidityType.UInt256, amount));

RLP Encoding

var item = RLP.Encode(

    // string
    "First item",

    // byte array
    "0x7cafb9c3de0fd02142754ce648ba7db04e4c161e".HexToBytes(),

    // single byte
    (byte)0xf5,

    // empty array
    new RLPItem[] { },

    // array of mixed types
    new RLPItem[]
    {
            "hello world",
            123456
    }
);

var expected = "0xf48a4669727374206974656d947cafb9c3de0fd02142754ce648ba7db04e4c161e81f5c0d08b68656c6c6f20776f726c648301e240";
Assert.Equal(expected, item.ToHexString(hexPrefix: true));

Testing Contract Deployment Reverts

[TestMethod]
public async Task ExpectDeploymentRevert()
{
    // Expect revert on normal deployment.
    await SomeContract.New(RpcClient).ExpectRevert();

    // Expect revert on deployment from Accounts[1].
    await SomeContract.New(RpcClient, new TransactionParams { From = Accounts[1] }).ExpectRevert();
}


// Or use the ExpectException attribute
[TestMethod]
[ExpectedException(typeof(ContractExecutionException))]
public async Task ExpectDeploymentRevert()
{
    await SomeContract.New(RpcClient);
}

Change current block time

await RpcClient.IncreaseTime({seconds}):

Hit fallback function in a contract

[TestMethod]
public async Task Fallback()
{
    await token.FallbackFunction.ExpectRevertTransaction(new TransactionParams { Value = 100 });
}

Working timestamp / datetimes

When working with a Crowdsale or time related contracts it is best to use relative DateTime objects instead of hardcoded timestamps in TestMethods. Example of how to create relative DateTime objects with conversions to unix timestamps:

// Unix timestamp
var start = 1408346285;

// Create DateTime UTC timezone and convert to Unix timestamp in seconds
var start = DateTimeOffset.UtcNow.ToUnixTimeSeconds();

// Create DateTime UTC based on Unix timestamp, add 100 days and convert back to Unix timestamp in seconds
var start = (DateTimeOffset.FromUnixTimeSeconds(1408346285) + TimeSpan.FromDays(100)).ToUnixTimeSeconds(); 

Testing ABI correctness

A strongly typed ABI object array is exposed on the contract which can be used to verify a contract interface/implementation.

var testEvent = from a in _contract.Abi
                where a.Type == AbiType.Event
                where a.Name == "TestEvent"
                select a;

Assert.IsTrue(testEvent.Any());

var balancesFunction = from a in _contract.Abi
                       where a.Type == AbiType.Function
                       where a.Name == "balance"
                       where a.Inputs.SingleOrDefault()?.Type == "address"
                       where a.Outputs.SingleOrDefault()?.Type == "uint256"
                       select a;

Assert.IsTrue(balancesFunction.Any());