Introduction
Ethereum contracts represent self-executing agreements with predefined rules encoded on the blockchain. This guide explores two fundamental aspects:
- Contract Creation: How smart contracts originate on the Ethereum network
- Message Calls: How contracts communicate and interact with each other
๐ Discover advanced Ethereum development techniques
Ethereum Contract Fundamentals
Core Concepts
Smart contracts function as autonomous programs operating within the Ethereum Virtual Machine (EVM) environment. Key characteristics:
- Isolated Execution: EVM provides sandboxed runtime completely segregated from host systems
Account Types:
- External Accounts: Controlled by private keys (user wallets)
- Contract Accounts: Governed by their embedded code
- Uniform Addressing: All accounts use 160-bit addresses within the same namespace
Contract Creation Process
Creating a contract involves sending a transaction with:
- Empty recipient field (
to: null) - Compiled bytecode in the data field
- Sufficient gas allocation
Creation Example
pragma solidity ^0.4.21;
contract MyContract {
event Log(address addr);
function MyContract() public {
emit Log(this);
}
function add(uint256 a, uint256 b) public pure returns(uint256) {
return a + b;
}
}Deployment Steps:
- Compile bytecode
Send creation transaction:
web3.eth.sendTransaction({ from: senderAddress, to: null, data: MyContract.bytecode, gas: 4600000 });- Verify deployment via transaction receipt
๐ Explore real-world contract deployment strategies
Message Calls Between Contracts
Call Mechanisms
Contracts communicate through message calls with these components:
- Sender address
- Recipient address
- Payload data
- Transferred value (ETH)
- Gas allocation
Basic Call Syntax
address.call.gas(gasAmount).value(etherValue)(payloadData);Delegatecall Specialization
A delegatecall preserves the calling contract's context:
msg.senderremains unchangedmsg.valuepersists from original transaction- Executed code accesses caller's storage
Example Scenario:
contract Greeter {
event Thanks(address sender, uint256 value);
function thanks() public payable {
emit Thanks(msg.sender, msg.value);
}
}
contract Wallet {
Greeter internal greeter;
function Wallet() public {
greeter = new Greeter();
}
function () public payable {
greeter.delegatecall(bytes4(keccak256("thanks()")));
}
}Key Observations:
Walletforwards calls toGreeter- Event logs show original
msg.senderandmsg.value - Storage modifications affect
Walletcontract
Frequently Asked Questions
Why can't I call contract functions during construction?
Contract code isn't stored until after constructor execution completes. Attempting to call functions during this phase will fail because:
- The account exists but contains no executable code yet
- This prevents circular dependencies during initialization
How does gas allocation work with nested calls?
The EVM reserves 1/64th of remaining gas for the calling context:
- Prevents complete gas exhaustion from inner calls
- Allows graceful error handling when nested calls fail
- Demonstrated in our
Caller/Implementationexample
When should I use delegatecall vs regular calls?
Use delegatecall when you need:
- Library-like code reuse
- Upgradeable contract patterns
- Context preservation (original sender/value)
Storage modifications will affect the calling contract, not the delegated contract.
Advanced Call Patterns
Assembly-Level Calls
For precise control, use EVM opcodes directly:
assembly {
let result := delegatecall(
gasAmount, // Gas to forward
targetAddress, // Contract to delegatecall
memPointer, // Memory location of call data
dataSize, // Call data length
0, // Where to store return data
0 // Return data size
)
}Storage Management with Delegatecall
Our Calculator example demonstrates shared storage access:
contract Calculator is ResultStorage {
function add(uint256 x) public {
addition.delegatecall(bytes4(keccak256("calculate(uint256)")), x);
}
}
contract Addition is ResultStorage {
function calculate(uint256 x) public {
result += x; // Modifies Calculator's storage
}
}Key points:
- All contracts inherit
ResultStorage - Storage modifications persist to calling contract
- Enables modular design patterns
Conclusion
This deep dive covered:
- The contract creation lifecycle
- Message call mechanics and gas management
- Context preservation with
delegatecall - Practical implementation examples
For comprehensive Ethereum development knowledge including storage handling and memory management, continue with Part 2 of this series.
๐ Master Ethereum development with professional resources