Ethereum Contract Inheritance
This is an excerpt from the Concurrence Exploration of Contract Inheritance.
This is an excerpt from the Concurrence Exploration of Contract Inheritance.
Very intelligent people before us have found common patterns in Ethereum contracts and published standardized and hardened examples to extend. We will stand on their shoulders using contract inheritance for some parts of our fleet. Let’s dig into an example of how this works.
Instead of coding up our own layer of ownership and possibly introducing insecurities, let’s look at inheriting from OpenZeppelin’s zeppelin-solidity repo.
We’ll create a contract called Inherit that will explore inheriting OpenZeppelin’s Ownable contract:
This light-weight contract has only one state variable, the message string, and it can only be set by the owner. Instead of handling the logic ourselves, we use a modifier from the Ownable contract.
Also, before we can deploy, the Inherit contract will need to add a dependencies.js:
const fs = require('fs');
module.exports = { 'zeppelin-solidity/contracts/ownership/Ownable.sol': fs.readFileSync('zeppelin-solidity/contracts/ownership/Ownable.sol', 'utf8') }
And an arguments.js to pass in a string to the Inherit() constructor.
const fs = require('fs'); module.exports = ["Ethereum is totally rad!"]
Now we can compile and deploy Inherit:
node compile Inherit node deploy Inherit
Contract address on Ropsten testnet:
0xd5fa4a24897db806d4879fd72c1637af5c83af65
We’ll want a script that can tell us what the current message is on the Inherit contract:
module.exports = (contract,params,args)=>{ contract.methods.message().call().then((message)=>{ console.log("MESSAGE:"+message) })}
node contract getMessage Inherit
MESSAGE:Ethereum is totally rad!
We’ll also want a script that can tell us what account is the current owner:
module.exports = (contract,params,args)=>{ contract.methods.owner().call().then((owner)=>{ console.log("OWNER:"+owner) }) }
node contract getOwner Inherit
OWNER:0xA3EEBd575245E0bd51aa46B87b1fFc6A1689965a
Awesome, so it looks like stuff is setup correctly. Now, let’s see if it functions correctly when we try a setMessage.js script:
module.exports = (contract,params,args)=>{ console.log("**== setting message to "+args[6]+" with account "+params.accounts[args[5]]) return contract.methods.setMessage(args[6]).send({ from: params.accounts[args[5]], gas: params.gas, gasPrice:params.gasPrice }) }
node contract setMessage Inherit null 1 "WHAT'S GUCC'?"
(Transaction with status: ‘0x0’ on etherscan.io)
node contract getMessage Inherit
MESSAGE:WHAT'S GUCC'?
Great, we seem to be secure without having to write and audit our own ownership functionality. One last test of inheritance would be to see if the transferOwnership() function built into the Ownable contract will just work for our contract.
We’ll need a transferOwnership.js script:
module.exports = (contract,params,args)=>{ console.log("**== transferring ownership from "+params.accounts[args[5]]+" to "+args[6]) return contract.methods.transferOwnership(args[6]).send({ from: params.accounts[args[5]], gas: params.gas, gasPrice:params.gasPrice }) }
(Transaction on etherscan.io)
node contract getOwner Inherit
OWNER:0x4fFD642A057Ce33579a3CA638347b402B909f6D6
After writing Solidity for a while and trying to be super safe and working through as many possible scenarios as we can think of, it’s really nice to be able to rely on a trusted third party that has already had plenty of eyes on their code. As the ecosystem grows, projects will have more and more audits and we’ll be able to trust more and more libraries.
Read more at https://concurrence.io.