Solidity Smart Contract “Gotchas” watch out!

BadgeForce Engineering
4 min readDec 11, 2017

--

Ethereum development is hot right now, there are dozens of ICO’s and Daaps springing up everyday. When I first started developing with Solidity writing smart contracts I came across a few gotchas that left me pulling my hair out for hours. I scoured StackOverflow for answers and clues which cost me precious development time. I will list a few of the pitfalls that I fell victim to and hopefully save you some time.

Dynamic arrays and Structs

Currently the EVM does not support returning dynamically sized arrays from functions (https://github.com/ethereum/solidity/issues/166). You might attempt to return an array of structs like this.

There are two problems with our People contract here. The first on line 19 will give you a compiler error.

TypeError: Type struct People.Person memory is not implicitly convertible to expected type struct People.Person storage pointer.
Person newPerson = Person(_wallet, _firstname, _lastname);

This is because when no storage keyword is used storage is used by default. Consequently Person newPerson is a pointer to the contract’s storage space, and the way Solidity handles storage requires deriving that address from the organization of the structs you’re writing it to — that is, its address in storage is directly dependent on the variable you’re going to store it in. Without knowing what variable it’s going in, it can’t write to storage. Thus you must remember to use the memory keyword when creating temporary structs inside functions, these variables will be destroyed after the function execution is finished and must be persisted to the contracts storage explicitly.

The second problem is the getPeople function on line 24. This will give you the infamous invalid opcode error when you try to execute this function after deploying the contract because the EVM does not support returning dynamically sized arrays. Let’s update our People contract to work.

Notice we added the memory keyword on line 19. We also created a getPerson function that will return a single person rather than an array of them. You can also add a getNumberOfPeople function to inform the UI about how many people exists and then fetch each person one by one. Note that if your structs contain more complex data such as arrays or maps this will not work for the same reasons, thus you will need to return significant data manually.

Working with truffle and testrpc

Sometimes when working with truffle and testrpc your artifacts can become out of wack. You may see that when compiling and redeploying your deployed contract does not contain the updates that you added. When this happens I tend to simply remove the build directory and run truffle migrate again. Also, be aware that the JSON ABI output of your contracts contain a network id property. For example, you may be developing a UI or API to interface with your deployed contract while using the truffle-contract package for performing contract transactions. If your JSON ABI is stale or out of date you may see web3 errors in your daap stating the contract is not deployed on the network, when this happens it’s good to restart testrpc and recompile/deploy your contract then use the newly output JSON ABI files.

To ease this issue, it’s smart to keep the updated working versions of your contract ABI files accessible to yourself or team members working with you. This will allow everyone to reliably develop with the same version of the contract that is currently released.

Meet doug

Doug is a Github webhook server written in Go that will listen process the release webhook for your smart contract projects and upload specified JSON ABI files to S3 for consumption by your daap or development daaps. Simply configure some projects, and artifact file names and host the server somewhere. Now whenever you create a new release of these smart contracts doug will put the compiled JSON ABI files on S3 for you. Continuing with our People contract as an example, this is what that would look like.

Clone the doug repo. Now we will open up the config.toml file and configure our People smart contract project. Make sure to add env variables for S3 credentials AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY

Now whenever we release a new version of our People project doug will take the Person.json file under the build/contracts/ directory created by truffle and upload it to S3 with the path nomenclature of bucket-name/project-name/version/file-name, our Person.json file would be accessible using the following URL from S3 https://s3.amazonaws.com/myorganization-artifacts/People/0.0.1/Person.json. We now provide development teams and contributors a more reliable source for our contracts JSON ABI.

--

--