Deploying a smart contract to Ethereum
Never before in history has a technology existed where anyone from anywhere can publicly deploy code that will immediately and indefinitely…
Never before in history has a technology existed where anyone from anywhere can publicly deploy code that will immediately and indefinitely run on tens of thousands of nodes simultaneously and deterministically. Further, thanks to cryptography and cryptoeconomics, this technology is ownerless, trustless, and incentivized to continue. Once a contract is deployed, it is effectively autonomous, eternal, and controlled only by the laws of machines.
Let’s make our mark on the blockchain.
Here is a Simple contract that holds a public count:
pragma solidity ^0.4.11;
contract Simple { uint8 public count; function Simple(uint8 _amount) { count = _amount; }
function add(uint8 _amount) { count += _amount; }
}
The count is initialized in the constructor Simple().
If you are using our open source Concurrence Scripts you can run:
node compile Simple
This produces a big chunk of bytecode:
6060604052341561000f57600080fd5b60405160208061011a833981016040528080516000805460ff90921660ff19909216919091179055505060d3806100476000396000f300606060405263ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166302067e6a8114604557806306661abd14605d57600080fd5b3415604f57600080fd5b605b60ff600435166083565b005b3415606757600080fd5b606d609e565b60405160ff909116815260200160405180910390f35b6000805460ff19811660ff9182169390930116919091179055565b60005460ff16815600a165627a7a723058203b071253b061d82c255e5006105dfcb6234b29200503a45f7a55c842c0dbc10a0029
To learn more about this bytecode, check out the this post on stackexchange. If you really want to get weird, you can also dive into the Ethereum Yellow Paper (toward the bottom).
Let’s deploy this bytecode to the testnet:
node deploy Simple
Also, you’ll need an arguments.js file to pass a number into the constructor:
module.exports = [253]
The output of the deploy looks like this:
paying a max of 2000000 gas @ the price of 22 gwei (22000000000) ... ==ETHER COST: 0.0029070139999999994 $1.0174548999999997
At the price of 22gwei, it looks like it cost a dollar to deploy.
Now, anyone from anywhere, for the rest of the life of the testnet, can interact with this contract at 0xd68ef7611913d0aff3627a92f5e502696887d626. That’s pretty rad!
Let’s poke around on this contract and see what shakes loose. We’ll want to craft up a few scripts so we aren’t fumbling around on the command line:
//// usage: node contract getCount Simple//module.exports = (contract,params,args)=>{ contract.methods.count().call().then((count)=>{ console.log("COUNT:"+count) })}
node contract getCount Simple
COUNT:253
Neat, so our current count is 253 and that’s what we deployed the contract with.
This was a read-only action, we didn’t change the state of the contract so reading the count is free for anyone to do as long as they are connected to the Ethereum blockchain.
Let’s run the add() function on the contract to actually change the state.
//// usage: node contract add Simple null #AMOUNT#//// ex: node contract add Simple null 1//module.exports = (contract,params,args)=>{ console.log("**== adding "+args[5]) return contract.methods.add(args[5]).send({ from: params.accounts[0], gas: params.gas, gasPrice:params.gasPrice })}
node contract add Simple null 1
Success{ blockHash: '0x78ad780d0bf95737baec82f974e067d4ee67708829cbd4dad4fda15c3de39a51', blockNumber: 1856672, contractAddress: null, cumulativeGasUsed: 26840, from: '0x4ffd642a057ce33579a3ca638347b402b909f6d6', gasUsed: 26840, status: '0x1', to: '0xd68ef7611913d0aff3627a92f5e502696887d626', transactionHash: '0x78a472410ada67aa2345d37fb4d695e1e07702940aae51616efacb7e4b01621c', transactionIndex: 0}
View transaction on etherscan.io.
Now let’s do another getCount() and see what the state of the contract is:
node contract getCount Simple
COUNT:254
According to Etherscan, to add 1 to that uint it costs about $0.17. That might seem kind of expensive, but what’s actually going on there?
Well, we broadcast to the network that we want to make a transaction, some lucky miner is able to find the correct nonce through brute force cpu power, mines the block containing our transaction and others, broadcasts that to the rest of the network, and then every miner in the world runs our transaction against their version of our contract and gets the same result. We could then ask any of them what our count is and it would be the same. Even as banks, businesses, and governments rise and fall, our count stays exactly where it’s instructed to stay. That is pretty freakin’ awesome.
Let’s play around with gas cost a little more because contract interaction cost plays a huge role in how Concurrence will work.
Let’s lower what we are willing to pay by 1⁄10:
echo "2" > gasprice.int
Now let’s run the same transaction again:
node contract add Simple null 1
Checking on the count now, we see:
COUNT:255
View transaction on etherscan.io.
Last time it took about 25 seconds to go through. This time it took 55 seconds but the cost was $0.017 or so. This is because the miners are not only incentivized by block mining rewards but also the gas used to run the transactions. It’s up to them to determine which transactions are worth mining. We can trade cost for speed depending on our needs.
(Another neat tool provided by etherscan.io is the vmtrace. You can see each step of the transaction including OPCODE and cost. Check out how much SSTORE is compared to everything else.)
We should also touch on security and bugs. This contract is public, so anyone can run the add function and anyone can see the current count. That’s fine for now, but what if there were 100 million USD at stake… yikes! This makes the job of contract developers extremely difficult because everything you do is at the mercy of every bad actor for the rest of time. Every contract interaction is deterministic; we can determine for sure what will happen given a state and an action, but just like a move in chess, predicting every single possible outcome on a chess board is also relatively difficult.
So what happens if we run add() one more time? Assuming no one else has already hit our contract, the count will go up just like before and we should see 256 right? Let’s try it:
node contract add Simple null 1
View transaction on etherscan.io.
Checking on the count now, we see:
COUNT:0
Oh shart! Our account balance is 0! H4ckers! Well, not exactly, more like uint8 overflow, but you get the idea. It is incredibly important that you understand every aspect of every possibility your contract can encounter because a lot of real money is on the line.
This is an excerpt from Deploying A Contract section on Concurrence.io.