diff --git a/polkadot/network/Cargo.toml b/polkadot/network/Cargo.toml
index eb861e626596b701751e1bb2189863f4a73ebec1..d109ef7628e3cff57b2b7f5a1ccf23a953470688 100644
--- a/polkadot/network/Cargo.toml
+++ b/polkadot/network/Cargo.toml
@@ -12,6 +12,7 @@ polkadot-consensus = { path = "../consensus" }
 polkadot-primitives = { path = "../primitives" }
 substrate-bft = { path = "../../substrate/bft" }
 substrate-codec = { path = "../../substrate/codec" }
+substrate-codec-derive = { path = "../../substrate/codec/derive" }
 substrate-network = { path = "../../substrate/network" }
 substrate-primitives = { path = "../../substrate/primitives" }
 ed25519 = { path = "../../substrate/ed25519" }
diff --git a/polkadot/network/src/collator_pool.rs b/polkadot/network/src/collator_pool.rs
index 7070eece88c20cd74738c0f8d78f728179f47f04..c4541856104e8973bd5ef89e8a0f83fe2c0967b1 100644
--- a/polkadot/network/src/collator_pool.rs
+++ b/polkadot/network/src/collator_pool.rs
@@ -18,7 +18,6 @@
 
 use polkadot_primitives::{AccountId, Hash};
 use polkadot_primitives::parachain::{Id as ParaId, Collation};
-use codec;
 
 use futures::sync::oneshot;
 
@@ -28,7 +27,7 @@ use std::time::{Duration, Instant};
 const COLLATION_LIFETIME: Duration = Duration::from_secs(60 * 5);
 
 /// The role of the collator. Whether they're the primary or backup for this parachain.
-#[derive(PartialEq, Debug, Clone, Copy)]
+#[derive(PartialEq, Debug, Clone, Copy, Encode, Decode)]
 pub enum Role {
 	/// Primary collators should send collations whenever it's time.
 	Primary = 0,
@@ -36,22 +35,6 @@ pub enum Role {
 	Backup = 1,
 }
 
-impl codec::Encode for Role {
-	fn encode_to<T: codec::Output>(&self, dest: &mut T) {
-		dest.push_byte(*self as u8);
-	}
-}
-
-impl codec::Decode for Role {
-	fn decode<I: codec::Input>(input: &mut I) -> Option<Self> {
-		match input.read_byte()? {
-			x if x == Role::Primary as u8 => Some(Role::Primary),
-			x if x == Role::Backup as u8 => Some(Role::Backup),
-			_ => None,
-		}
-	}
-}
-
 /// A maintenance action for the collator set.
 #[derive(PartialEq, Debug)]
 #[allow(dead_code)]
diff --git a/polkadot/network/src/lib.rs b/polkadot/network/src/lib.rs
index 366a2f659b92361dfde4b42d77f0037b8c51cb11..48b382f66258e7cda7f9e37c3267687abce3d641 100644
--- a/polkadot/network/src/lib.rs
+++ b/polkadot/network/src/lib.rs
@@ -38,13 +38,15 @@ extern crate rhododendron;
 
 #[macro_use]
 extern crate log;
+#[macro_use]
+extern crate substrate_codec_derive;
 
 mod collator_pool;
 mod local_collations;
 mod router;
 pub mod consensus;
 
-use codec::{Decode, Encode, Input, Output};
+use codec::{Decode, Encode};
 use futures::sync::oneshot;
 use parking_lot::Mutex;
 use polkadot_consensus::{Statement, SignedStatement, GenericStatement};
@@ -74,36 +76,11 @@ type FullStatus = GenericFullStatus<Block>;
 pub type NetworkService = ::substrate_network::Service<Block, PolkadotProtocol>;
 
 /// Status of a Polkadot node.
-#[derive(Debug, PartialEq, Eq, Clone)]
+#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
 pub struct Status {
 	collating_for: Option<(AccountId, ParaId)>,
 }
 
-impl Encode for Status {
-	fn encode_to<T: codec::Output>(&self, dest: &mut T) {
-		match self.collating_for {
-			Some(ref details) => {
-				dest.push_byte(1);
-				dest.push(details);
-			}
-			None => {
-				dest.push_byte(0);
-			}
-		}
-	}
-}
-
-impl Decode for Status {
-	fn decode<I: codec::Input>(input: &mut I) -> Option<Self> {
-		let collating_for = match input.read_byte()? {
-			0 => None,
-			1 => Some(Decode::decode(input)?),
-			_ => return None,
-		};
-		Some(Status { collating_for })
-	}
-}
-
 struct BlockDataRequest {
 	attempted_peers: HashSet<SessionKey>,
 	consensus_parent: Hash,
@@ -207,7 +184,7 @@ impl CurrentConsensus {
 }
 
 /// Polkadot-specific messages.
-#[derive(Debug)]
+#[derive(Debug, Encode, Decode)]
 pub enum Message {
 	/// signed statement and localized parent hash.
 	Statement(Hash, SignedStatement),
@@ -224,59 +201,6 @@ pub enum Message {
 	Collation(Hash, Collation),
 }
 
-impl Encode for Message {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		match *self {
-			Message::Statement(ref h, ref s) => {
-				dest.push_byte(0);
-				dest.push(h);
-				dest.push(s);
-			}
-			Message::SessionKey(ref k) => {
-				dest.push_byte(1);
-				dest.push(k);
-			}
-			Message::RequestBlockData(ref id, ref r, ref d) => {
-				dest.push_byte(2);
-				dest.push(id);
-				dest.push(r);
-				dest.push(d);
-			}
-			Message::BlockData(ref id, ref d) => {
-				dest.push_byte(3);
-				dest.push(id);
-				dest.push(d);
-			}
-			Message::CollatorRole(ref r) => {
-				dest.push_byte(4);
-				dest.push(r);
-			}
-			Message::Collation(ref h, ref c) => {
-				dest.push_byte(5);
-				dest.push(h);
-				dest.push(c);
-			}
-		}
-	}
-}
-
-impl Decode for Message {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		match input.read_byte()? {
-			0 => Some(Message::Statement(Decode::decode(input)?, Decode::decode(input)?)),
-			1 => Some(Message::SessionKey(Decode::decode(input)?)),
-			2 => {
-				let x: (_, _, _) = Decode::decode(input)?;
-				Some(Message::RequestBlockData(x.0, x.1, x.2))
-			}
-			3 => Some(Message::BlockData(Decode::decode(input)?, Decode::decode(input)?)),
-			4 => Some(Message::CollatorRole(Decode::decode(input)?)),
-			5 => Some(Message::Collation(Decode::decode(input)?, Decode::decode(input)?)),
-			_ => None,
-		}
-	}
-}
-
 fn send_polkadot_message(ctx: &mut Context<Block>, to: NodeIndex, message: Message) {
 	trace!(target: "p_net", "Sending polkadot message to {}: {:?}", to, message);
 	let encoded = message.encode();
diff --git a/polkadot/parachain/Cargo.toml b/polkadot/parachain/Cargo.toml
index 2197911ed42d5d09d547a6af652e7a9c276f4bb4..f9e2b3bf05588d1e8168f6f5e4e9cd0b9eed98f4 100644
--- a/polkadot/parachain/Cargo.toml
+++ b/polkadot/parachain/Cargo.toml
@@ -6,6 +6,7 @@ description = "Types and utilities for creating and working with parachains"
 
 [dependencies]
 substrate-codec = { path = "../../substrate/codec", default-features = false }
+substrate-codec-derive = { path = "../../substrate/codec/derive", default-features = false }
 wasmi = { version = "0.4", optional = true }
 error-chain = { version = "0.12", optional = true }
 
diff --git a/polkadot/parachain/src/lib.rs b/polkadot/parachain/src/lib.rs
index 7af248fdbeaa4a6fdf5305b326e6765484b624b2..3854fe2ca8c33022c2f6541a0f560f4b812ecc9f 100644
--- a/polkadot/parachain/src/lib.rs
+++ b/polkadot/parachain/src/lib.rs
@@ -46,6 +46,9 @@
 /// Re-export of substrate-codec.
 pub extern crate substrate_codec as codec;
 
+#[macro_use]
+extern crate substrate_codec_derive;
+
 #[cfg(not(feature = "std"))]
 extern crate alloc;
 
@@ -61,14 +64,14 @@ extern crate error_chain;
 
 #[cfg(not(feature = "std"))]
 use alloc::vec::Vec;
-use codec::{Encode, Decode, Input, Output};
+use codec::{Encode, Decode};
 
 #[cfg(feature = "std")]
 pub mod wasm;
 
 /// Validation parameters for evaluating the parachain validity function.
 // TODO: consolidated ingress and balance downloads
-#[derive(PartialEq, Eq)]
+#[derive(PartialEq, Eq, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Debug))]
 pub struct ValidationParams {
 	/// The collation body.
@@ -77,45 +80,15 @@ pub struct ValidationParams {
 	pub parent_head: Vec<u8>,
 }
 
-impl Encode for ValidationParams {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		dest.push(&self.block_data);
-		dest.push(&self.parent_head);
-	}
-}
-
-impl Decode for ValidationParams {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Some(ValidationParams {
-			block_data: Decode::decode(input)?,
-			parent_head: Decode::decode(input)?,
-		})
-	}
-}
-
 /// The result of parachain validation.
 // TODO: egress and balance uploads
-#[derive(PartialEq, Eq)]
+#[derive(PartialEq, Eq, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Debug))]
 pub struct ValidationResult {
 	/// New head data that should be included in the relay chain state.
 	pub head_data: Vec<u8>
 }
 
-impl Encode for ValidationResult {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		dest.push(&self.head_data);
-	}
-}
-
-impl Decode for ValidationResult {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Some(ValidationResult {
-			head_data: Decode::decode(input)?,
-		})
-	}
-}
-
 /// Load the validation params from memory when implementing a Rust parachain.
 ///
 /// Offset and length must have been provided by the validation
diff --git a/polkadot/parachain/tests/adder.rs b/polkadot/parachain/tests/adder.rs
index 485eb41bcf8716aa3858503127b0db81c243a27f..7ba3ff04fe843a4efaa267700259d3842cab0951 100644
--- a/polkadot/parachain/tests/adder.rs
+++ b/polkadot/parachain/tests/adder.rs
@@ -16,66 +16,35 @@
 
 //! Basic parachain that adds a number as part of its state.
 
+#[macro_use]
+extern crate substrate_codec_derive;
+extern crate substrate_codec as codec;
 extern crate polkadot_parachain as parachain;
 extern crate tiny_keccak;
 
 use parachain::ValidationParams;
-use parachain::codec::{Decode, Encode, Input, Output};
+use codec::{Decode, Encode};
 
-// Head data for this parachain.
-#[derive(Default, Clone)]
+/// Head data for this parachain.
+#[derive(Default, Clone, Encode, Decode)]
 struct HeadData {
-	// Block number
+	/// Block number
 	number: u64,
-	// parent block keccak256
+	/// parent block keccak256
 	parent_hash: [u8; 32],
-	// hash of post-execution state.
+	/// hash of post-execution state.
 	post_state: [u8; 32],
 }
 
-impl Encode for HeadData {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		dest.push(&self.number);
-		dest.push(&self.parent_hash);
-		dest.push(&self.post_state);
-	}
-}
-
-impl Decode for HeadData {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Some(HeadData {
-			number: Decode::decode(input)?,
-			parent_hash: Decode::decode(input)?,
-			post_state: Decode::decode(input)?,
-		})
-	}
-}
-
-// Block data for this parachain.
-#[derive(Default, Clone)]
+/// Block data for this parachain.
+#[derive(Default, Clone, Encode, Decode)]
 struct BlockData {
-	// State to begin from.
+	/// State to begin from.
 	state: u64,
-	// Amount to add (overflowing)
+	/// Amount to add (overflowing)
 	add: u64,
 }
 
-impl Encode for BlockData {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		dest.push(&self.state);
-		dest.push(&self.add);
-	}
-}
-
-impl Decode for BlockData {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Some(BlockData {
-			state: Decode::decode(input)?,
-			add: Decode::decode(input)?,
-		})
-	}
-}
-
 const TEST_CODE: &[u8] = include_bytes!("res/adder.wasm");
 
 fn hash_state(state: u64) -> [u8; 32] {
diff --git a/polkadot/parachain/tests/res/adder.wasm b/polkadot/parachain/tests/res/adder.wasm
index 93f354400f5e85e8be3c700daa76034ea0a023df..9f0145a78b1ba6bedc78efb63e862e61f91f29bd 100644
Binary files a/polkadot/parachain/tests/res/adder.wasm and b/polkadot/parachain/tests/res/adder.wasm differ
diff --git a/polkadot/primitives/Cargo.toml b/polkadot/primitives/Cargo.toml
index dc424468dc18bda14b70dae6fadaee96c1af65b0..b277f074c3fe5f3548ed909f552f54bfda2d4489 100644
--- a/polkadot/primitives/Cargo.toml
+++ b/polkadot/primitives/Cargo.toml
@@ -7,6 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
 serde = { version = "1.0", default_features = false }
 serde_derive = { version = "1.0", optional = true }
 substrate-codec = { path = "../../substrate/codec", default_features = false }
+substrate-codec-derive = { path = "../../substrate/codec/derive", default_features = false }
 substrate-primitives = { path = "../../substrate/primitives", default_features = false }
 substrate-runtime-std = { path = "../../substrate/runtime-std", default_features = false }
 substrate-runtime-primitives = { path = "../../substrate/runtime/primitives", default_features = false }
diff --git a/polkadot/primitives/src/lib.rs b/polkadot/primitives/src/lib.rs
index 83118799bb3550498eccf12e737cda7676d46c63..99ca00314cbc2b8de0b4a83f0eb41d3a342baf46 100644
--- a/polkadot/primitives/src/lib.rs
+++ b/polkadot/primitives/src/lib.rs
@@ -21,13 +21,16 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 #![cfg_attr(not(feature = "std"), feature(alloc))]
 
-extern crate substrate_runtime_std as rstd;
+extern crate substrate_codec as codec;
 extern crate substrate_primitives as primitives;
 extern crate substrate_runtime_primitives as runtime_primitives;
+extern crate substrate_runtime_std as rstd;
+
 #[cfg(test)]
 extern crate substrate_serializer;
 
-extern crate substrate_codec as codec;
+#[macro_use]
+extern crate substrate_codec_derive;
 
 #[cfg(feature = "std")]
 #[macro_use]
@@ -42,7 +45,6 @@ use primitives::bytes;
 use rstd::prelude::*;
 use runtime_primitives::traits::BlakeTwo256;
 use runtime_primitives::generic;
-use codec::{Encode, Decode, Input, Output};
 
 pub mod parachain;
 
@@ -105,18 +107,6 @@ pub type Balance = u128;
 pub type BlockId = generic::BlockId<Block>;
 
 /// A log entry in the block.
-#[derive(PartialEq, Eq, Clone, Default)]
+#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
-
-impl Decode for Log {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Vec::<u8>::decode(input).map(Log)
-	}
-}
-
-impl Encode for Log {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		self.0.encode_to(dest)
-	}
-}
diff --git a/polkadot/primitives/src/parachain.rs b/polkadot/primitives/src/parachain.rs
index ff7580067e1019ce78939ad5b33625dd01abee13..8ceec3f9fd5f50c4ad204f9bd6b282b18db1c721 100644
--- a/polkadot/primitives/src/parachain.rs
+++ b/polkadot/primitives/src/parachain.rs
@@ -16,7 +16,6 @@
 
 //! Polkadot parachain types.
 
-use codec::{Encode, Decode, Input, Output};
 use rstd::prelude::*;
 use rstd::cmp::Ordering;
 use super::Hash;
@@ -28,7 +27,7 @@ use primitives::bytes;
 pub type CandidateSignature = ::runtime_primitives::Ed25519Signature;
 
 /// Unique identifier of a parachain.
-#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 pub struct Id(u32);
 
@@ -47,20 +46,8 @@ impl Id {
 	}
 }
 
-impl Decode for Id {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		u32::decode(input).map(Id)
-	}
-}
-
-impl Encode for Id {
-	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
-		self.0.using_encoded(f)
-	}
-}
-
 /// Identifier for a chain, either one of a number of parachains or the relay chain.
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, PartialEq, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Debug))]
 pub enum Chain {
 	/// The relay chain.
@@ -69,31 +56,8 @@ pub enum Chain {
 	Parachain(Id),
 }
 
-impl Decode for Chain {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		let disc = input.read_byte()?;
-		match disc {
-			0 => Some(Chain::Relay),
-			1 => Some(Chain::Parachain(Decode::decode(input)?)),
-			_ => None,
-		}
-	}
-}
-
-impl Encode for Chain {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		match *self {
-			Chain::Relay => { dest.push_byte(0); }
-			Chain::Parachain(id) => {
-				dest.push_byte(1u8);
-				dest.push(&id);
-			}
-		}
-	}
-}
-
 /// The duty roster specifying what jobs each validator must do.
-#[derive(Clone, PartialEq)]
+#[derive(Clone, PartialEq, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Default, Debug))]
 pub struct DutyRoster {
 	/// Lookup from validator index to chain on which that validator has a duty to validate.
@@ -103,22 +67,6 @@ pub struct DutyRoster {
 	pub guarantor_duty: Vec<Chain>,
 }
 
-impl Decode for DutyRoster {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Some(DutyRoster {
-			validator_duty: Decode::decode(input)?,
-			guarantor_duty: Decode::decode(input)?,
-		})
-	}
-}
-
-impl Encode for DutyRoster {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		dest.push(&self.validator_duty);
-		dest.push(&self.guarantor_duty);
-	}
-}
-
 /// Extrinsic data for a parachain.
 #[derive(PartialEq, Eq, Clone)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
@@ -127,7 +75,7 @@ impl Encode for DutyRoster {
 pub struct Extrinsic;
 
 /// Candidate receipt type.
-#[derive(PartialEq, Eq, Clone)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
 #[cfg_attr(feature = "std", serde(deny_unknown_fields))]
@@ -150,34 +98,6 @@ pub struct CandidateReceipt {
 	pub block_data_hash: Hash,
 }
 
-impl Encode for CandidateReceipt {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		dest.push(&self.parachain_index);
-		dest.push(&self.collator);
-		dest.push(&self.signature);
-		dest.push(&self.head_data.0);
-		dest.push(&self.balance_uploads);
-		dest.push(&self.egress_queue_roots);
-		dest.push(&self.fees);
-		dest.push(&self.block_data_hash);
-	}
-}
-
-impl Decode for CandidateReceipt {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Some(CandidateReceipt {
-			parachain_index: Decode::decode(input)?,
-			collator: Decode::decode(input)?,
-			signature: Decode::decode(input)?,
-			head_data: Decode::decode(input).map(HeadData)?,
-			balance_uploads: Decode::decode(input)?,
-			egress_queue_roots: Decode::decode(input)?,
-			fees: Decode::decode(input)?,
-			block_data_hash: Decode::decode(input)?,
-		})
-	}
-}
-
 impl CandidateReceipt {
 	/// Get the blake2_256 hash
 	#[cfg(feature = "std")]
@@ -213,7 +133,7 @@ impl Ord for CandidateReceipt {
 }
 
 /// A full collation.
-#[derive(PartialEq, Eq, Clone)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))]
 #[cfg_attr(feature = "std", serde(deny_unknown_fields))]
@@ -224,22 +144,6 @@ pub struct Collation {
 	pub receipt: CandidateReceipt,
 }
 
-impl Decode for Collation {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Some(Collation {
-			block_data: Decode::decode(input)?,
-			receipt: Decode::decode(input)?,
-		})
-	}
-}
-
-impl Encode for Collation {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		dest.push(&self.block_data);
-		dest.push(&self.receipt);
-	}
-}
-
 /// Parachain ingress queue message.
 #[derive(PartialEq, Eq, Clone)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
@@ -256,7 +160,7 @@ pub struct ConsolidatedIngress(pub Vec<(Id, Vec<Message>)>);
 /// Parachain block data.
 ///
 /// contains everything required to validate para-block, may contain block and witness data
-#[derive(PartialEq, Eq, Clone)]
+#[derive(PartialEq, Eq, Clone, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 pub struct BlockData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
 
@@ -268,26 +172,13 @@ impl BlockData {
 		BlakeTwo256::hash(&self.0[..])
 	}
 }
-
-impl Decode for BlockData {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Some(BlockData(Decode::decode(input)?))
-	}
-}
-
-impl Encode for BlockData {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		dest.push(&self.0);
-	}
-}
-
 /// Parachain header raw bytes wrapper type.
 #[derive(PartialEq, Eq)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 pub struct Header(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
 
 /// Parachain head data included in the chain.
-#[derive(PartialEq, Eq, Clone, PartialOrd, Ord)]
+#[derive(PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
 
@@ -297,22 +188,10 @@ pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8
 pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
 
 /// Activitiy bit field
-#[derive(PartialEq, Eq, Clone, Default)]
+#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec<u8>);
 
-impl Decode for Activity {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Vec::<u8>::decode(input).map(Activity)
-	}
-}
-
-impl Encode for Activity {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		self.0.encode_to(dest)
-	}
-}
-
 /// Statements which can be made about parachain candidates.
 #[derive(Clone, PartialEq, Eq)]
 #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))]
diff --git a/polkadot/runtime/wasm/Cargo.lock b/polkadot/runtime/wasm/Cargo.lock
index a2c3b0413a358799bff6797b283287c2b12d19c3..697159e57edb73ce02fb9f49eb55dfe508c1d5f6 100644
--- a/polkadot/runtime/wasm/Cargo.lock
+++ b/polkadot/runtime/wasm/Cargo.lock
@@ -454,6 +454,7 @@ dependencies = [
  "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
  "substrate-codec 0.1.0",
+ "substrate-codec-derive 0.1.0",
  "substrate-primitives 0.1.0",
  "substrate-runtime-primitives 0.1.0",
  "substrate-runtime-std 0.1.0",
@@ -639,7 +640,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [[package]]
 name = "rustc-hex"
 version = "2.0.0"
-source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc891d6dc2cc9009d7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rustc_version"
@@ -706,6 +707,15 @@ dependencies = [
  "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "substrate-codec-derive"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "substrate-keyring"
 version = "0.1.0"
@@ -723,10 +733,11 @@ dependencies = [
  "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
- "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)",
+ "rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
  "substrate-codec 0.1.0",
+ "substrate-codec-derive 0.1.0",
  "substrate-runtime-std 0.1.0",
  "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)",
@@ -781,6 +792,7 @@ dependencies = [
  "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
  "substrate-codec 0.1.0",
+ "substrate-codec-derive 0.1.0",
  "substrate-primitives 0.1.0",
  "substrate-runtime-consensus 0.1.0",
  "substrate-runtime-io 0.1.0",
@@ -831,6 +843,7 @@ dependencies = [
  "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
  "substrate-codec 0.1.0",
+ "substrate-codec-derive 0.1.0",
  "substrate-primitives 0.1.0",
  "substrate-runtime-io 0.1.0",
  "substrate-runtime-std 0.1.0",
@@ -954,6 +967,7 @@ dependencies = [
  "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
  "substrate-codec 0.1.0",
+ "substrate-codec-derive 0.1.0",
  "substrate-runtime-std 0.1.0",
  "substrate-runtime-support 0.1.0",
 ]
@@ -1206,7 +1220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rlp 0.2.1 (git+https://github.com/paritytech/parity.git)" = "<none>"
 "checksum rlp 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "89db7f8dfdd5eb7ab3ac3ece7a07fd273a680b4b224cb231181280e8996f9f0b"
 "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e"
-"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "<none>"
+"checksum rustc-hex 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b03280c2813907a030785570c577fb27d3deec8da4c18566751ade94de0ace"
 "checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
diff --git a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm
index 831b77b45e1c1f8dcbcc7780e361380736c2f18f..c2f710732e26ac9502cb58c805bfe73bcae40392 100644
Binary files a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm and b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm differ
diff --git a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm
index 8d09a81248bc35e0292bd9c0f13b67fe1c70a186..033090ce56f6670ccc41f32ff766a86b1361bf6b 100755
Binary files a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm and b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm differ
diff --git a/polkadot/statement-table/Cargo.toml b/polkadot/statement-table/Cargo.toml
index b81ee1db907e18789b3d229e05991ebd5aab89fd..97e35d1f5f07c14e48c8148b7bc5a21b6328cc4e 100644
--- a/polkadot/statement-table/Cargo.toml
+++ b/polkadot/statement-table/Cargo.toml
@@ -5,5 +5,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
 
 [dependencies]
 substrate-codec = { path = "../../substrate/codec" }
+substrate-codec-derive = { path = "../../substrate/codec/derive" }
 substrate-primitives = { path = "../../substrate/primitives" }
 polkadot-primitives = { path = "../primitives" }
diff --git a/polkadot/statement-table/src/generic.rs b/polkadot/statement-table/src/generic.rs
index 06f9f94292799faf7720b8320925499b43fff048..2a6c828f5b3254fd902614bd5ad3769157c16801 100644
--- a/polkadot/statement-table/src/generic.rs
+++ b/polkadot/statement-table/src/generic.rs
@@ -31,8 +31,6 @@ use std::collections::hash_map::{HashMap, Entry};
 use std::hash::Hash;
 use std::fmt::Debug;
 
-use codec::{Decode, Encode, Input, Output};
-
 /// Context for the statement table.
 pub trait Context {
 	/// A authority ID
@@ -70,78 +68,30 @@ pub trait Context {
 }
 
 /// Statements circulated among peers.
-#[derive(PartialEq, Eq, Debug, Clone)]
+#[derive(PartialEq, Eq, Debug, Clone, Encode, Decode)]
 pub enum Statement<C, D> {
 	/// Broadcast by a authority to indicate that this is his candidate for
 	/// inclusion.
 	///
 	/// Broadcasting two different candidate messages per round is not allowed.
+	#[codec(index = "1")]
 	Candidate(C),
 	/// Broadcast by a authority to attest that the candidate with given digest
 	/// is valid.
+	#[codec(index = "2")]
 	Valid(D),
-	/// Broadcast by a authority to attest that the auxiliary data for a candidate
-	/// with given digest is available.
-	Available(D),
 	/// Broadcast by a authority to attest that the candidate with given digest
 	/// is invalid.
+	#[codec(index = "3")]
 	Invalid(D),
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-#[repr(u8)]
-enum StatementKind {
-	Candidate = 1,
-	Valid = 2,
-	Invalid = 3,
-	Available = 4,
-}
-
-impl<C: Encode, D: Encode> Encode for Statement<C, D> {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		match *self {
-			Statement::Candidate(ref candidate) => {
-				dest.push_byte(StatementKind::Candidate as u8);
-				dest.push(candidate);
-			}
-			Statement::Valid(ref digest) => {
-				dest.push_byte(StatementKind::Valid as u8);
-				dest.push(digest);
-			}
-			Statement::Invalid(ref digest) => {
-				dest.push_byte(StatementKind::Invalid as u8);
-				dest.push(digest);
-			}
-			Statement::Available(ref digest) => {
-				dest.push_byte(StatementKind::Available as u8);
-				dest.push(digest);
-			}
-		}
-	}
-}
-
-impl<C: Decode, D: Decode> Decode for Statement<C, D> {
-	fn decode<I: Input>(value: &mut I) -> Option<Self> {
-		match value.read_byte() {
-			Some(x) if x == StatementKind::Candidate as u8 => {
-				Decode::decode(value).map(Statement::Candidate)
-			}
-			Some(x) if x == StatementKind::Valid as u8 => {
-				Decode::decode(value).map(Statement::Valid)
-			}
-			Some(x) if x == StatementKind::Invalid as u8 => {
-				Decode::decode(value).map(Statement::Invalid)
-			}
-			Some(x) if x == StatementKind::Available as u8 => {
-				Decode::decode(value).map(Statement::Available)
-			}
-			_ => None,
-		}
-	}
+	/// Broadcast by a authority to attest that the auxiliary data for a candidate
+	/// with given digest is available.
+	#[codec(index = "4")]
+	Available(D),
 }
 
 /// A signed statement.
-#[derive(PartialEq, Eq, Debug, Clone)]
+#[derive(PartialEq, Eq, Debug, Clone, Encode, Decode)]
 pub struct SignedStatement<C, D, V, S> {
 	/// The statement.
 	pub statement: Statement<C, D>,
@@ -151,23 +101,6 @@ pub struct SignedStatement<C, D, V, S> {
 	pub sender: V,
 }
 
-impl<C: Encode, D: Encode, V: Encode, S: Encode> Encode for SignedStatement<C, D, V, S> {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		dest.push(&self.statement);
-		dest.push(&self.signature);
-		dest.push(&self.sender);
-	}
-}
-
-impl<C: Decode, D: Decode, V: Decode, S: Decode> Decode for SignedStatement<C, D, V, S> {
-	fn decode<I: Input>(value: &mut I) -> Option<Self> {
-		Some(SignedStatement {
-			statement: Decode::decode(value)?,
-			signature: Decode::decode(value)?,
-			sender: Decode::decode(value)?,
-		})
-	}
-}
 /// Misbehavior: voting more than one way on candidate validity.
 ///
 /// Since there are three possible ways to vote, a double vote is possible in
diff --git a/polkadot/statement-table/src/lib.rs b/polkadot/statement-table/src/lib.rs
index ecbe832b6a530568fb588e35c0659326fc79b62b..02457ac4ae4252eca1605262f32d171e6b4c1b7a 100644
--- a/polkadot/statement-table/src/lib.rs
+++ b/polkadot/statement-table/src/lib.rs
@@ -18,6 +18,9 @@ extern crate substrate_codec as codec;
 extern crate substrate_primitives;
 extern crate polkadot_primitives as primitives;
 
+#[macro_use]
+extern crate substrate_codec_derive;
+
 pub mod generic;
 
 pub use generic::Table;
diff --git a/polkadot/test-parachains/adder/Cargo.toml b/polkadot/test-parachains/adder/Cargo.toml
index 1ff06689dd0cf854784ad6d6575c721911d9f472..2b41ba9bfa95830a3bb2b0ac53ce67697b098fde 100644
--- a/polkadot/test-parachains/adder/Cargo.toml
+++ b/polkadot/test-parachains/adder/Cargo.toml
@@ -6,4 +6,5 @@ description = "Test parachain which adds to a number as its state transition"
 
 [dependencies]
 polkadot-parachain = { path = "../../parachain/", default-features = false }
+substrate-codec-derive = { path = "../../../substrate/codec/derive", default-features = false }
 tiny-keccak = "1.4"
diff --git a/polkadot/test-parachains/adder/src/lib.rs b/polkadot/test-parachains/adder/src/lib.rs
index aa23dea7772cf74577c6be87cee4fad3db0dba13..a0491ec23b720a93124a037b14b0a180847481b8 100644
--- a/polkadot/test-parachains/adder/src/lib.rs
+++ b/polkadot/test-parachains/adder/src/lib.rs
@@ -18,13 +18,16 @@
 
 #![no_std]
 
+#[macro_use]
+extern crate substrate_codec_derive;
+
 extern crate polkadot_parachain as parachain;
 extern crate tiny_keccak;
 
-use parachain::codec::{Decode, Encode, Input, Output};
+use parachain::codec::{self, Encode};
 
 /// Head data for this parachain.
-#[derive(Default, Clone, Hash, Eq, PartialEq)]
+#[derive(Default, Clone, Hash, Eq, PartialEq, Encode, Decode)]
 pub struct HeadData {
 	/// Block number
 	pub number: u64,
@@ -40,26 +43,8 @@ impl HeadData {
 	}
 }
 
-impl Encode for HeadData {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		dest.push(&self.number);
-		dest.push(&self.parent_hash);
-		dest.push(&self.post_state);
-	}
-}
-
-impl Decode for HeadData {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Some(HeadData {
-			number: Decode::decode(input)?,
-			parent_hash: Decode::decode(input)?,
-			post_state: Decode::decode(input)?,
-		})
-	}
-}
-
 /// Block data for this parachain.
-#[derive(Default, Clone)]
+#[derive(Default, Clone, Encode, Decode)]
 pub struct BlockData {
 	/// State to begin from.
 	pub state: u64,
@@ -67,22 +52,6 @@ pub struct BlockData {
 	pub add: u64,
 }
 
-impl Encode for BlockData {
-	fn encode_to<T: Output>(&self, dest: &mut T) {
-		dest.push(&self.state);
-		dest.push(&self.add);
-	}
-}
-
-impl Decode for BlockData {
-	fn decode<I: Input>(input: &mut I) -> Option<Self> {
-		Some(BlockData {
-			state: Decode::decode(input)?,
-			add: Decode::decode(input)?,
-		})
-	}
-}
-
 pub fn hash_state(state: u64) -> [u8; 32] {
 	::tiny_keccak::keccak256(state.encode().as_slice())
 }