Making a Birthday Contract.

Intermediate Solidity Ethereum Notes & Development.

Let’s make a Birthday smart contract in Solidity.

Note/selfplug: If you are looking for an introduction to Ethereum, Solidity and Smart Contracts I just published an eBook on getting started:
https://www.amazon.com/dp/B078CQ8L7V

The Problem / challenge:

  • To have a contract record it’s birth on the blockchain.
  • To have the contract tell you it’s Birthday.
  • Bonus / Extra Credit: Return the Birthday in a Human Readable way without the need of external UI’s.

The contract :

pragma solidity ^ 0.4.0;
contract DateTime {
function getYear(uint timestamp) public constant returns (uint16);
function getMonth(uint timestamp) public constant returns (uint8);
function getDay(uint timestamp) public constant returns (uint8);
}
contract BirthDay {
uint public bday;
address public dateTimeAddr = 0x8Fc065565E3e44aef229F1D06aac009D6A524e82;
DateTime dateTime = DateTime(dateTimeAddr);
  function BirthDay() public  {
bday = now;
}
  function getBirthYear() view public returns (uint16){
return dateTime.getYear(bday);
}
  function getBirthMonth() view public returns (uint8){
return dateTime.getMonth(bday);
}
  function getBirthDay() view public returns (uint8){
return dateTime.getDay(bday);
}
}

Read the Contract :

https://kovan.etherscan.io/address/0x86d686cc0e2feaa63834163af8b7a5fb869bb977#readContract

Development Notes :

The first thing this contract does is record it’s birthday via the now native function which is saved into a variable bday by the constructor:

uint public bday;
function BirthDay() public  {
bday = now;
}

As it is a public variable, you get an automagic getter so anyone can consult it :

bday -> 1512417464 uint256

Now, dates in Solidity use timestamps, and if you are a developer you shouldn't have much issue converting this unix timestamp to a human readable date… But I personally believe it would be useful to provide a human readable date for you could easily consult without having a complex client or wallet.

Now in order to do so we will be adding considerable overhead and for some reason it is frowned upon, but this is an excercise so this is what we are going to do:

  1. We will use an external contract library to parse the timestamp :
I'll use Piper Merriam's DateTime contract:
https://github.com/pipermerriam/ethereum-datetime
If you want to check it out or use it I deployed and verified a copy in Kovan:
https://kovan.etherscan.io/address/0x8fc065565e3e44aef229f1d06aac009d6a524e82

2. Calling this library contract.

There are multiple ways of calling another contract in solidity depending on what it is you want to accomplish, (read a view, affect state, have an ABI, don’t have one). In this specific case, all we want to do is send a timestamp and get the return value, we also have the ABI in the form of the DateTimesAPI.json found on the repo.

The First thing we need is to include our ABI in the form of an abstract contract:
contract DateTime {
Followed by the function signatures we will use:
function getYear(uint timestamp) public constant returns (uint16);
function getMonth(uint timestamp) public constant returns (uint8);
function getDay(uint timestamp) public constant returns (uint8);
}
Upon compiling we just feed the :Birthday contract and it will include this one.

The address for our previously deployed DateTime library comes next, it is hardcoded and public although it seems sensible to provide an ownable setter and maybe make it private if need be.
address public dateTimeAddr = 0x8Fc065565E3e44aef229F1D06aac009D6A524e82;

The next step is to create a globally accessible contract instance of the DateTime Library at our specific address:
DateTime dateTime = DateTime(dateTimeAddr);
A tongue twister of a thing that basically says this is an instance of our abstract contract at this address.

And finally we can use our library inside functions like so:

function getBirthYear() view public returns (uint16){
return dateTime.getYear(bday);
}

The result :

I really wanted to return a single line in the form of day-month-year, but concatenating multiple returns while calling external functions seems to be a fools errand, so I settled for calling them individually, you can query the contract without any external UI and it returns it’s Birthday in pieces (as well as a timestamp):

Wrapping up.

This is such an interesting contract, for one having the ability to record a contracts birth inside the same contract allows for all kinds of interesting autonomous applications based on time. ( I actually needed this feature for a future payable contract ).

On the other hand there is a considerable degree of sophistication needed to add the human readable date feature via a library call. I personally think that it is worth it as a means to provide the convenience to the end user, but every project is different.

We also learned how to call an external contract, something that will surely be useful in future contracts.

Best,

Keno

About the Author :

Born Eugenio Noyola Leon (Keno) I am a Designer,Web Developer/programmer, Artist and Inventor, currently living in Mexico City, you can find me at www.k3no.com