Top Posts
Most Shared
Most Discussed
Most Liked
Most Recent
By Paula Livingstone on Sept. 15, 2021, 7:13 p.m.
Welcome to this comprehensive guide on mastering Ethereum transactions. If you've ever wondered how transactions work in the Ethereum network, you're in the right place. This blog post aims to provide you with a deep understanding of the subject, from the basic structure of transactions to the role of nonces in ensuring transaction integrity.
Transactions are the backbone of any blockchain network, and Ethereum is no exception. They serve as the mechanism through which state changes occur in the network. Understanding transactions is crucial for anyone involved in Ethereum, whether you're a developer, investor, or just a curious individual.
While transactions may seem straightforward at first glance, they involve a complex interplay of various components. This guide will dissect these components one by one, providing you with the knowledge you need to navigate the Ethereum network effectively. We'll also delve into the concept of nonces, a critical but often misunderstood aspect of Ethereum transactions.
So, why should you care about Ethereum transactions? Well, they are the building blocks of decentralized applications (dApps) and smart contracts. A solid grasp of how transactions work will not only make you more informed but also enable you to interact with the Ethereum ecosystem more efficiently.
Whether you're new to Ethereum or looking to deepen your understanding, this guide has something for everyone. Let's dive in and explore the fascinating world of Ethereum transactions.
Similar Posts
Here are some other posts you might enjoy after enjoying this one.
What is an Ethereum Transaction?
Let's start by defining what an Ethereum transaction is. In the simplest terms, a transaction is a signed data package that stores a message to be sent from an externally owned account to another account on the Ethereum network. This account could either be another externally owned account or a smart contract.
It's essential to note that transactions in Ethereum are not just about transferring Ether, the native cryptocurrency. They can also involve deploying a smart contract, calling a function on a smart contract, or even making changes to the existing data on the blockchain. This versatility makes Ethereum transactions unique compared to those in other blockchain networks.
For example, if Alice wants to send Bob 1 Ether, she would create a transaction specifying Bob's address as the recipient and 1 Ether as the amount. This transaction would then be broadcast to the Ethereum network for validation and inclusion in a block. But if Alice wants to interact with a smart contract, say to vote in a decentralized voting application, the transaction would contain instructions for that specific function call.
Transactions are the means by which any change occurs on the Ethereum network. Whether you're transferring funds, interacting with a smart contract, or deploying new code, it all happens through transactions. They are the fundamental units of operation, the building blocks that enable the Ethereum network to function as a decentralized platform for various applications.
Understanding the nature and role of transactions in Ethereum is the first step in grasping the network's broader mechanics. They serve as the gateway to more complex operations and functionalities, laying the foundation for everything else we'll discuss in this guide.
Components of an Ethereum Transaction
Now that we've established what an Ethereum transaction is, it's time to delve into its components. A typical Ethereum transaction consists of several fields, each serving a specific purpose. These fields include the nonce, gas price, gas limit, recipient address, value, data, and the digital signature components (v, r, s).
The nonce is a sequence number issued by the originating account, ensuring that each transaction is unique. The gas price and gas limit fields are related to transaction fees and computational work, respectively. The recipient address specifies where the transaction is headed, while the value field indicates the amount of Ether being sent.
For instance, consider a transaction where you're sending 2 Ether to a friend. The nonce would be the next available sequence number for your account, the gas price would be the fee you're willing to pay per unit of gas, and the gas limit would be the maximum amount of gas you're willing to consume for this transaction. The recipient address would be your friend's Ethereum address, and the value would be 2 Ether.
The data field is particularly interesting because it can contain either the input data for a contract function call or additional information for the transaction. In the case of a simple Ether transfer, this field is usually empty. However, if you're interacting with a smart contract, the data field will contain the function's signature and arguments.
Lastly, the digital signature components (v, r, s) are cryptographic elements that prove the transaction was signed by the originating account. These are generated using the private key of the account and are crucial for transaction validation.
Understanding each of these components is vital for anyone looking to interact with the Ethereum network effectively. They not only dictate how a transaction is processed but also influence its speed and cost. In the following sections, we'll explore these components in greater detail.
How Transactions are Serialized
Serialization is the process of converting the structured data of a transaction into a format that can be easily stored or transmitted. In Ethereum, this is achieved through Recursive Length Prefix (RLP) encoding. Understanding this encoding scheme is crucial for grasping how transactions are processed and stored in the Ethereum network.
RLP encoding is not just a random choice; it serves specific purposes. It's a space-efficient method that allows for faster transaction processing. Moreover, it ensures that the serialized data can be easily deserialized back into its original structure, which is vital for transaction verification and execution.
Let's consider an example to illustrate this. Suppose you're sending 3 Ether to a friend. After filling in all the necessary fields like nonce, gas price, and recipient address, the transaction data needs to be serialized before it's broadcast to the network. RLP encoding takes these disparate pieces of information and converts them into a single string of bytes. This byte string is what actually gets transmitted and stored.
It's worth noting that RLP encoding is not exclusive to Ethereum transactions. It's also used in other parts of the Ethereum protocol, such as in the serialization of blocks and messages between nodes. This uniformity in encoding schemes simplifies data handling across the network, making it more efficient.
While the technical details of RLP encoding may seem daunting, the key takeaway is its role in facilitating efficient data storage and transmission. It's an integral part of how transactions move through the Ethereum network, affecting everything from transaction speed to network scalability.
As we continue to explore the intricacies of Ethereum transactions, the importance of serialization and RLP encoding will become increasingly evident. They serve as the underpinning for many of the network's functionalities, setting the stage for more advanced topics we'll cover later.
How Transactions Affect State Change
One of the most fundamental aspects of Ethereum transactions is their ability to affect state changes in the network. But what exactly does "state change" mean? In Ethereum, the state refers to the current information stored on the blockchain, including account balances, smart contract data, and more. A state change, therefore, is any modification to this information.
When you send Ether to another account, you're essentially changing the state of both your account and the recipient's account. Your balance decreases, and the recipient's balance increases. This is a straightforward example, but state changes can be more complex, especially when smart contracts are involved.
For instance, if you're interacting with a decentralized finance (DeFi) application to borrow funds, multiple state changes occur. Your collateral is locked, your loan amount is credited, and the smart contract's internal data is updated to reflect this new loan. All of these changes are facilitated through transactions.
It's not just financial transactions that lead to state changes. Even actions like voting in a decentralized organization or updating your profile in a decentralized social network result in state changes. These changes are permanent and immutable once confirmed, thanks to the blockchain's inherent characteristics.
State changes are not isolated events; they have network-wide implications. For example, when a new smart contract is deployed, it becomes a part of the Ethereum state, accessible and interactable by anyone on the network. This is why understanding the impact of transactions on state changes is crucial for anyone engaging with Ethereum.
As we delve deeper into the complexities of Ethereum transactions, you'll find that state changes are the common thread linking all activities. Whether it's transferring Ether, executing smart contracts, or even more advanced operations, transactions serve as the catalysts for state changes, making them the heartbeat of the Ethereum network.
Common Use-Cases for Transactions
By now, you should have a solid understanding of what Ethereum transactions are and how they function. But what are the typical scenarios where these transactions come into play? Ethereum's versatility allows for a wide range of use-cases, far beyond simple fund transfers.
One of the most common uses is, of course, transferring Ether between accounts. Whether you're sending money to a friend or paying for services, this is the most straightforward application of Ethereum transactions. But the utility of transactions extends much further.
Smart contracts open up a whole new realm of possibilities. For example, you could use transactions to interact with a decentralized exchange, swapping Ether for another cryptocurrency. Or perhaps you're involved in a decentralized finance (DeFi) platform where transactions are used to stake tokens, earn interest, or borrow assets.
Another intriguing use-case is Non-Fungible Tokens (NFTs). When you buy, sell, or transfer an NFT, you're executing transactions that change the ownership state of unique digital assets. These transactions are fundamentally different from regular Ether transfers, as they involve interacting with a specific type of smart contract that adheres to the ERC-721 standard.
Transactions also play a role in governance models of decentralized organizations. For instance, if you hold tokens in a Decentralized Autonomous Organization (DAO), you can use transactions to vote on proposals or even submit new ones. Your votes are transactions that affect the state of the DAO's smart contract.
As you can see, the use-cases for Ethereum transactions are diverse and multifaceted. They serve as the mechanism for a wide array of activities on the network, each with its own set of rules and implications. This adaptability is one of the reasons why Ethereum has become such a robust and versatile platform for decentralized applications.
Transaction Lifecycle
Understanding the lifecycle of an Ethereum transaction can provide valuable insights into how the network operates. A transaction doesn't simply go from point A to point B; it undergoes a series of steps, each crucial for ensuring its validity and eventual execution.
The journey begins when a transaction is created by an externally owned account (EOA). This involves setting various parameters like the nonce, gas price, and recipient address. Once these are configured and the transaction is signed, it's ready to be broadcast to the Ethereum network.
After being broadcast, the transaction enters the transaction pool, a temporary holding area where it waits to be picked up by miners. Miners select transactions based on various factors, including the gas price. The higher the gas price, the more likely the transaction will be included in the next block.
Once a miner includes the transaction in a block and successfully mines that block, the transaction is considered "confirmed." However, it's generally advisable to wait for additional block confirmations to ensure the transaction is permanently part of the blockchain. This is because the blockchain can undergo reorganizations due to network forks, which could potentially exclude the transaction.
After sufficient confirmations, the transaction's effects are irreversible. If it was a fund transfer, the recipient's balance would have increased by now. If it was a smart contract interaction, the contract's state would have changed accordingly. At this point, the transaction has completed its lifecycle.
Understanding this lifecycle is not just academic; it has practical implications. For example, if your transaction is stuck in the transaction pool for too long, you might consider increasing the gas price for quicker processing. Or, if you're interacting with a smart contract, knowing the lifecycle stages can help you troubleshoot issues like failed transactions.
What is a Nonce?
As we delve deeper into the intricacies of Ethereum transactions, one term that frequently comes up is 'nonce.' But what exactly is a nonce in the context of Ethereum? A nonce is a number that is used only once, and in Ethereum, it serves to identify the sequence of transactions coming from a single account.
Every externally owned account (EOA) in Ethereum has an associated nonce, starting from zero. Each time you send a transaction, the nonce increases by one. This ensures that transactions are processed in the order they were created, maintaining the integrity of the account's transaction history.
For example, if you've already sent five transactions from your Ethereum account, the nonce for your next transaction will be six. This is automatically managed by most Ethereum wallets, but it's crucial to understand the concept, especially if you're interacting with the network programmatically.
Nonces are not just arbitrary numbers; they serve a critical function. They prevent replay attacks, where a malicious actor could rebroadcast a transaction to siphon funds from an account. Because each nonce can be used only once for a transaction, rebroadcasting a transaction with the same nonce would be rejected by the network.
It's also worth noting that nonces are specific to the account and not to the transaction itself. This means that if you have multiple accounts, each will have its own sequence of nonces. This is an important distinction that can affect how you manage multiple Ethereum accounts.
Understanding the concept of nonces is foundational to grasping how Ethereum transactions work. They are a simple yet powerful mechanism that ensures transactions are unique, ordered, and secure. As we proceed, we'll explore more about why nonces are so crucial and how they interact with other aspects of Ethereum transactions.
Why Nonces are Important
Having established what a nonce is, let's delve into its significance in the context of Ethereum transactions. Nonces are not just a technical requirement; they serve critical roles in ensuring the integrity and security of transactions.
One of the primary functions of a nonce is to guarantee the uniqueness of each transaction from an account. By attaching a sequential number to transactions, nonces ensure that each transaction is distinct, eliminating the risk of accidental duplication. This is particularly useful in high-throughput scenarios where multiple transactions are being sent in quick succession.
Another crucial role of nonces is in the prevention of replay attacks. In a replay attack, a malicious actor could take a previously executed transaction and rebroadcast it, aiming to duplicate the transaction's effects. However, because each nonce can only be used once, the network would reject any attempt to rebroadcast a transaction with an already-used nonce.
Nonces also contribute to the orderly processing of transactions. In a network as decentralized and distributed as Ethereum, ensuring that transactions are processed in the order they were issued is no small feat. Nonces provide a simple yet effective way to maintain this order, thereby preserving the consistency of the blockchain's state.
Furthermore, nonces have implications for transaction fees. Since miners prioritize transactions based on gas price, a transaction with a lower nonce will generally be processed before one with a higher nonce, even if the latter has a higher gas price. This is important to consider when sending multiple transactions.
As you can see, the importance of nonces in Ethereum transactions cannot be overstated. They are a fundamental aspect that affects various facets of transaction processing, from security to orderliness to cost. Understanding their role is essential for anyone looking to navigate the Ethereum network effectively.
How Nonces Prevent Double Spending
One of the most critical security features facilitated by nonces is the prevention of double-spending. Double-spending is a form of fraud where the same digital asset is spent more than once. In the context of Ethereum, nonces make this kind of attack extremely difficult, if not impossible.
When you initiate a transaction, the nonce ensures that it's unique and can't be duplicated. If someone were to try and rebroadcast that transaction, the network would immediately recognize the duplicate nonce and reject the transaction. This is a simple yet effective way to prevent double-spending attacks.
For example, let's say you have 5 Ether in your account and you send 3 Ether to a friend. The transaction would have a specific nonce, let's say 10. If a malicious actor tries to rebroadcast this transaction, the network would reject it because the nonce 10 has already been used for a transaction from your account.
It's worth noting that nonces are not the only mechanism in place to prevent double-spending. The decentralized nature of the blockchain and the consensus algorithm also play roles. However, nonces are the first line of defense, ensuring that each transaction is unique and can only be processed once.
Additionally, the sequential nature of nonces adds another layer of security. Even if a malicious actor tries to issue a new transaction with the same amount but a different nonce, it won't be processed until all previous transactions with lower nonces are confirmed. This makes double-spending attacks not only detectable but also impractical to execute.
Understanding how nonces prevent double-spending is crucial for grasping the security mechanisms of Ethereum. They serve as a cornerstone in the network's defense against fraudulent activities, ensuring that your transactions are both unique and secure.
Dynamic Calculation of Nonces
While the concept of a nonce may seem static, the way it's calculated can be quite dynamic. Most Ethereum wallets automatically manage nonces for you, but understanding the underlying process can offer valuable insights, especially for those who interact with the Ethereum network programmatically.
Typically, the nonce starts at zero for a new Ethereum account and increments by one with each transaction. However, there are scenarios where the nonce calculation becomes more complex. For instance, if you're sending multiple transactions rapidly, or if a previous transaction is stuck due to low gas fees, the nonce management can get tricky.
Some advanced wallets and services offer dynamic nonce calculation, adjusting the nonce based on network conditions and pending transactions. This can be particularly useful in high-congestion periods where transaction fees are fluctuating rapidly. Dynamic nonce calculation aims to optimize both the speed and cost of transactions.
Let's consider a practical example. Suppose you've sent a transaction with a low gas fee, and it's stuck in the transaction pool. You decide to send another transaction with a higher gas fee. A dynamic nonce calculation would allow the second transaction to be processed before the first, effectively "jumping the queue," provided that both transactions are not dependent on each other.
However, it's essential to exercise caution when manually adjusting nonces, especially in a dynamic setting. Incorrect nonce management can lead to failed transactions or unintended consequences. Therefore, unless you're well-versed in Ethereum's inner workings, it's generally advisable to let your wallet handle nonce management.
Understanding the flexibility and dynamics of nonce calculation can empower users to optimize their interactions with the Ethereum network. Whether you're a casual user or a blockchain developer, grasping the nuances of dynamic nonce calculation can enhance your Ethereum experience.
Nonce Management in Wallets
For most users, nonce management is a behind-the-scenes operation handled by their Ethereum wallets. However, understanding how your wallet manages nonces can provide you with a more nuanced view of transaction processing and potentially help you troubleshoot issues.
Standard Ethereum wallets automatically calculate and increment the nonce for each transaction. They keep track of the last used nonce and simply add one to it for the next transaction. This straightforward approach works well for the majority of users who are not executing rapid, successive transactions.
However, some wallets offer more advanced features, like the ability to set custom nonces. This is particularly useful for users who want to "overwrite" a pending transaction that's stuck due to low gas fees. By sending a new transaction with the same nonce but a higher gas price, the new transaction can replace the old one, effectively canceling it.
Another advanced feature is the option to queue multiple transactions with consecutive nonces. This ensures that a series of transactions are processed in a specific order, which can be crucial for complex operations like interacting with multi-step smart contracts.
It's important to note that while these advanced features offer greater control, they also come with risks. Incorrectly setting a custom nonce can result in failed transactions or unexpected behavior. Therefore, these features are generally recommended only for experienced users who understand the implications of manual nonce management.
Whether you're a casual user or an Ethereum enthusiast, understanding how your wallet manages nonces can offer valuable insights into the transaction process. It can help you make more informed decisions and give you greater control over your interactions with the Ethereum network.
The Role of Nonces in Transaction Ordering
By now, it should be clear that nonces are not just a security feature but also play a vital role in the ordering of transactions. This aspect is particularly important in a decentralized system like Ethereum, where transactions from all over the world are being processed simultaneously.
When you send multiple transactions from a single account, the nonce ensures that they are processed in the order they were created. This is crucial for various reasons, one of which is the consistency of the blockchain's state. If transactions were processed out of order, it could lead to inconsistencies and errors, especially when interacting with complex smart contracts.
For example, let's say you're using a decentralized finance (DeFi) platform to first deposit collateral and then take out a loan. These actions need to occur in a specific sequence. If the loan transaction were to be processed before the deposit, it would fail because the required collateral wouldn't be in place. Nonces ensure that the deposit transaction is processed first, followed by the loan transaction.
Another area where the role of nonces in transaction ordering becomes evident is in Decentralized Autonomous Organizations (DAOs). Voting on proposals often involves multiple transactions that must occur in a specific order for the vote to be valid. Here again, nonces ensure the correct sequencing of transactions.
It's also worth noting that the importance of transaction ordering extends to the miners who include transactions in new blocks. They also rely on nonces to determine the sequence of transactions from a single account, ensuring that the blockchain remains a true and consistent ledger of all transactions.
Understanding the role of nonces in transaction ordering is essential for anyone looking to engage in more complex Ethereum activities. Whether you're a developer building on Ethereum or an end-user interacting with its various applications, the ordering of transactions is a key element that ensures the network's reliability and consistency.
Concurrency Issues in Ethereum
As we explore the complexities of Ethereum transactions, it's important to address the topic of concurrency. In computer science, concurrency refers to the ability of different parts or units of a system to execute independently but potentially in parallel. In Ethereum, concurrency issues can arise due to the decentralized and asynchronous nature of the network.
One common scenario where concurrency becomes a concern is during network congestion. When many users are sending transactions simultaneously, the Ethereum network has to manage these transactions in a way that maintains the integrity of the blockchain. Here, nonces play a role in ensuring that transactions from a single account are processed in the correct order.
However, nonces alone cannot solve all concurrency issues. For example, two different accounts might interact with the same smart contract at the same time, leading to what is known as a "race condition." In such cases, the outcome depends on which transaction gets processed first, and this can be influenced by factors like gas price and network latency.
Smart contracts themselves can also be designed to handle concurrency. Developers often implement mechanisms like mutexes or other locking techniques to ensure that contract functions are executed in a safe manner. These techniques can prevent undesirable outcomes like double-spending or other forms of transaction manipulation.
It's also worth noting that Ethereum 2.0, the upcoming upgrade to the network, aims to address some of these concurrency issues. By transitioning from a Proof-of-Work to a Proof-of-Stake consensus mechanism and introducing sharding, Ethereum 2.0 is expected to offer improved scalability and concurrency handling.
Understanding the challenges and solutions related to concurrency is crucial for both developers and users. While Ethereum has robust mechanisms in place to handle these issues, being aware of them can help you navigate the network more effectively and avoid potential pitfalls.
How Ethereum Differs from Bitcoin in Transaction Handling
Given that both Ethereum and Bitcoin are leading cryptocurrencies, comparisons between the two are inevitable. However, when it comes to transaction handling, the two networks operate quite differently, each with its own set of rules and mechanisms.
One of the most notable differences is the concept of a "smart contract" in Ethereum, which is absent in Bitcoin. While Bitcoin transactions are primarily for transferring value, Ethereum transactions can execute code, interact with smart contracts, and even create new contracts. This makes Ethereum more versatile but also introduces additional complexities in transaction handling.
Another key difference lies in the role of nonces. In Bitcoin, the term "nonce" is used in the context of mining, where it's a number that miners change to find a hash that meets certain criteria. In Ethereum, as we've extensively discussed, nonces are used to order transactions and prevent double-spending, serving a different purpose altogether.
Transaction fees also differ between the two networks. In Bitcoin, transaction fees are based on the size of the transaction in bytes. In Ethereum, fees are calculated based on computational complexity, bandwidth, and storage needs, commonly referred to as "gas."
Moreover, Ethereum allows for more complex transaction types, like multi-signature transactions and transactions that trigger decentralized applications (dApps). Bitcoin does offer some scripting capabilities, but they are far more limited compared to Ethereum's Turing-complete language.
Understanding these differences is crucial for anyone operating in the cryptocurrency space. Whether you're a developer, investor, or casual user, knowing how Ethereum's transaction handling differs from that of Bitcoin can help you make more informed decisions and appreciate the unique capabilities of each network.
Security Implications of Nonces
As we've discussed throughout this blog, nonces are integral to the functioning of Ethereum transactions. However, their role is not just operational; they have significant security implications as well.
Firstly, nonces are crucial in preventing replay attacks. A replay attack involves a malicious actor rebroadcasting a transaction to duplicate its effects. Because each nonce is unique and can only be used once, the Ethereum network would reject any transaction with a reused nonce, thereby thwarting such attacks.
Secondly, nonces contribute to the integrity of the blockchain. By ensuring that transactions are processed in the order they were issued, nonces help maintain a consistent state of the blockchain. This is particularly important for complex operations like multi-step smart contract interactions, where the order of transactions can affect the outcome.
However, it's important to note that incorrect nonce management can also pose security risks. For example, manually setting a nonce that is too low could result in the transaction being rejected or replaced. Similarly, setting a nonce that is too high could lead to the transaction being stuck in the transaction pool indefinitely.
Advanced users who opt for manual nonce management should exercise extreme caution. Mistakes in nonce setting can not only lead to failed transactions but also expose the user to additional risks, such as unintentional contract interactions or even financial loss.
Therefore, understanding the security implications of nonces is not just an academic exercise; it's a practical necessity for anyone interacting with the Ethereum network. Whether you're a casual user or a seasoned developer, being aware of the security aspects of nonces can help you navigate the Ethereum ecosystem more safely and effectively.
Key Takeaways
We've covered a lot of ground in this blog post, diving deep into the intricacies of Ethereum transactions. From understanding the basic components to exploring the role of nonces, we've touched upon various aspects that make Ethereum transactions unique and complex.
One of the key points to remember is the importance of nonces in ensuring the security and integrity of transactions. They prevent replay attacks, ensure transaction ordering, and contribute to the overall reliability of the Ethereum network.
Another takeaway is the dynamic nature of nonce calculation. While most wallets handle this automatically, understanding the underlying process can offer valuable insights, especially for those who are looking to optimize their transactions or interact with the Ethereum network programmatically.
We also discussed the challenges and solutions related to concurrency in Ethereum. As the network continues to evolve, especially with the upcoming Ethereum 2.0 upgrade, it's crucial to stay updated on how these issues are being addressed.
Lastly, we touched upon how Ethereum's transaction handling differs from that of Bitcoin. Whether you're a developer, investor, or casual user, understanding these differences can help you make more informed decisions in the cryptocurrency space.
These are just a few of the key points we've covered. Each section of this blog post offers a deeper understanding of specific aspects, and I encourage you to revisit them for a more comprehensive grasp of Ethereum transactions.
Conclusion
We've journeyed through the complex landscape of Ethereum transactions, dissecting each component and understanding its significance. From the basic structure of a transaction to the nuanced role of nonces, this blog post has aimed to provide a comprehensive overview of how transactions work in the Ethereum network.
Understanding Ethereum transactions is not just for developers or blockchain enthusiasts; it's valuable knowledge for anyone interested in the world of cryptocurrencies. As Ethereum continues to evolve and grow, staying informed about its inner workings will enable you to engage more effectively with the network, whether you're sending Ether, interacting with smart contracts, or participating in decentralized applications.
While this post has been extensive, it's worth noting that the world of Ethereum is ever-changing. New upgrades, like Ethereum 2.0, promise to bring about significant changes that could further impact how transactions are processed. Therefore, continuous learning is essential for anyone who wishes to remain active and informed in this dynamic ecosystem.
Thank you for taking the time to read this blog post. I hope it has been informative and has deepened your understanding of Ethereum transactions. Whether you're a newcomer to the blockchain space or a seasoned veteran, there's always something new to learn, and I encourage you to continue exploring.
Want to get in touch?
I'm always happy to hear from people. If youre interested in dicussing something you've seen on the site or would like to make contact, fill the contact form and I'll be in touch.
No comments yet. Why not be the first to comment?