From 5fb9633985a9563eb75b9125c222dd978307d0d2 Mon Sep 17 00:00:00 2001
From: Marcin Chrzanowski
+Sometimes you just need a Truffle contract object. If you're developing a
+full-blown Truffle project, this is easy for your "core" contracts, the ones you
+keep in your
+I ran into this while working on meta-tooling around smart contracts,
+specifically scripts for running upgrades of proxied contracts. To this end, I
+wanted to write unit tests that would use minimal example contracts with
+edge cases that might not easily appear "in nature". I want to keep these dummy
+contracts in a test resources directory rather than cluttering up the main
+
+Unfortunately, not all parts of the Truffle API are very well documented, but
+here's how I got my sweet, sweet Truffle contract wrappers.
+
+Before you go run off playing with your new contracts/
directory. Just
+artifacts.require
and call it a day. But what if you want to
+interact with a different contract?
+contracts/
.
+Getting the contract object
+
+import truffleContract = require('truffle-contract')
+const Contract = truffleContract({
+ abi: artifact.abi,
+ unlinked_binary: artifact.bytecode,
+})
+
+
+where artifact
is a standard solc build artifact, say parsed from a
+JSON file that truffle compile
outputs. The thing to note is that
+the bytecode is under an unlinked_binary
property.
+
+Making it usable
+Contract
, a few last
+housekeeping things to take care of. If you try, say, deploying this contract
+with Contract.new()
, you'll get a nasty error message saying
+
+
+Error: Contract error: Please call setProvider() first before calling new().
+
+
+Actually not that nasty since it tells you what you need to do to fix things!
+Call Contract.setProvider()
with a standard Web3 provider. If you
+already have a Web3 instance lying around,
+
+
+Contract.setProvider(web3.currentProvider) ++ +should do. + + +
+Last things last, at this point you would start seeing the following: + +
+Error: Contract has no network id set, cannot lookup artifact data. Either set +the network manually using Contract.setNetwork(), run Contract.detectNetwork(), +or use new(), at() or deployed() as a thenable which will detect the network +automatically. ++ +I resolved this by calling
Contract.setNetwork('development')
,
+given that this was in a unit tests context and would always execute against the
+'development'
Truffle network. You might need to pass in a
+different network name, or feel free to look into one of the other solutions
+suggested by the above error message.
+
+
+
+At this point you'll be able to call Contract.new()
to get a handle
+to a freshly deployed contract, or Contract.at(address)
to interact
+with an already deployed instance of the contract.
+
+Here's the little helper function I wrote to construct these Truffle objects: + +
+import truffleContract = require('truffle-contract') + +const makeTruffleContract = (artifact) => { + const Contract = truffleContract({ + abi: artifact.abi, + unlinked_binary: artifact.bytecode, + }) + Contract.setProvider(web3.currentProvider) + Contract.setNetwork('development') + + return Contract +} ++ + +
+If you're using any linked libraries in your contract, first deploy the
+libraries, then link them with
+Contract.link('LibraryName', libraryAddress)
.
+