NatSpec

This section will further elaborate what you can do with contracts and transactions building on a protocol NatSpec. Solidity implements smart comments doxigen style which then can be used to generate various facades meta documents of the code. One such use case is to generate custom messages for transaction confirmation that clients can prompt users with.

So we now extend the multiply7 contract with a smart comment specifying a custom confirmation message (notice).

contract test {
   /// @notice Will multiply `a` by 7.
   function multiply(uint a) returns(uint d) {
       return a * 7;
   }
}

The comment has expressions in between backticks which are to be evaluated at the time the transaction confirmation message is presented to the user. The variables that refer to parameters of method calls then are instantiated in accordance with the actual transaction data sent by the user (or the user's dapp). NatSpec support for confirmation notices is fully implemented in geth. NatSpec relies on both the abi definition as well as the userDoc component to generate the proper confirmations. Therefore in order to access that, the contract needs to have registered its contract info as described above.

Let us see a full example. As a very conscientious smart contract dev, you first create your contract and deploy according to the recommended steps above:

source = "contract test {
   /// @notice Will multiply `a` by 7.
   function multiply(uint a) returns(uint d) {
       return a * 7;
   }
}"
contract = eth.compile.solidity(source).test
MyContract = eth.contract(contract.info.abiDefinition)
contenthash = admin.saveInfo(contract.info, "~/dapps/shared/contracts/test/info.json")
MyContract.new({from: primary, data: contract.code}, function(error, contract){
  if(!error && contract.address) {
    admin.register(primary, contract.address, contenthash)
    // put it up on your favourite oldworld site:
    admin.registerUrl(contentHash, "http://dapphub.com/test/info.json")
  }
});

Note that if we use content addressed storage system like swarm the second step is unnecessary, since the contenthash is (deterministically translates to) the unique address of the content itself.

For the purposes of a painless example just simply use the file url scheme (not exactly the cloud, but will show you how it works) without needing to deploy.

admin.registerUrl(contentHash, "file:///home/nirname/dapps/shared/contracts/test/info.json")

Now you are done as a dev, so swap seats as it were and pretend that you are a user who is sending a transaction to the infamous multiply7 contract.

You need to start the client with the --natspec flag to enable smart confirmations and contractInfo fetching. You can also set it on the console with admin.startNatSpec() and admin.stopNatSpec().

geth --natspec --unlock primary console 2>> /tmp/eth.log

Now at the console type:

// obtain the abi definition for your contract
var info = admin.getContractInfo(address)
var abiDef = info.abiDefinition
// instantiate a contract for transactions
var Multiply7 = eth.contract(abiDef);
var myMultiply7 = Multiply7.at(address);

And now try to send an actual transaction:

> myMultiply7.multiply.sendTransaction(6, {from: eth.accounts[0]})
NatSpec: Will multiply 6 by 7. 
Confirm? [y/n] y
>

When this transaction gets included in a block, somewhere on a lucky miner's computer, 6 will get multiplied by 7, with the result ignored. Mission accomplished.

If the transaction is not picked up, we can see it with:

eth.pendingTransactions

This accumulates all the transactions sent, even the ones that were rejected and are not included in the current mined block (trans state). These latter can be shown by:

eth.getBlock("pending", true).transactions()

if you identify the index of your rejected transaction, you can resend it with modified gas limit and gas price (both optional parameters):

tx = eth.pendingTransactions[1]
eth.resend(tx, newGasPrice, newGasLimit)