In large-scale blockchain projects, implementing all functionalities within a single smart contract is impractical and counterproductive for teamwork. Code is typically organized into libraries or separate contracts with interfaces for cross-contract communication.
Understanding Contract Interactions
Solidity offers two primary approaches for code reuse:
- Libraries: Deploy reusable logic as libraries (similar to C/Java libraries). However, libraries cannot modify contract states since they prohibit
storagevariables. - New Contracts: When state modification is required, deploy new contracts and use inter-contract calls.
Here are the 4 methods for contract-to-contract calls in Solidity:
CALLCALLCODE(Deprecated)DELEGATECALLSTATICCALL
1. CALL vs. CALLCODE
| Feature | CALL | CALLCODE |
|---|---|---|
| Context | Modifies callee's storage | Modifies caller's storage |
| Use Case | Cross-contract state changes | Library-like behavior within caller |
๐ Master Solidity with real-world examples
Verification Code Example
contract A {
int public x;
function inc_call(address _contractAddress) public {
_contractAddress.call(bytes4(keccak256("inc()")));
}
function inc_callcode(address _contractAddress) public {
_contractAddress.callcode(bytes4(keccak256("inc()")));
}
}
contract B {
int public x;
function inc() public { x++; }
}Outcome:
CALLmodifies Contract B'sx.CALLCODEmodifies Contract A'sx.
2. CALLCODE vs. DELEGATECALL
| Feature | CALLCODE | DELEGATECALL |
|---|---|---|
msg.sender | Uses caller contract address | Preserves original EOA address |
| Status | Deprecated | Recommended alternative |
Key Insight
DELEGATECALL maintains the original transaction sender's address, making it essential for proxy contracts and upgradeable patterns.
contract B {
event senderAddr(address);
function inc() public {
emit senderAddr(msg.sender);
// CALLCODE: emits Contract A's address
// DELEGATECALL: emits EOA address
}
}3. STATICCALL
Currently, Solidity compiles view and pure functions with runtime checks. Future implementations may use STATICCALL opcode to enforce read-only behavior at runtime.
Characteristics:
- Reverts if state modifications are attempted
- Ideal for querying data without gas costs for state changes
Summary Table
| Method | Context | State Change | msg.sender | Use Case |
|---|---|---|---|---|
CALL | Callee | Yes | Caller contract | General cross-contract calls |
CALLCODE | Caller | Yes | Caller contract | (Deprecated) |
DELEGATECALL | Caller | Yes | Original EOA | Proxy patterns |
STATICCALL | Callee | No | Caller contract | Read-only queries |
๐ Explore advanced Solidity techniques
FAQ
Q1: When should I use DELEGATECALL?
A: Use it for proxy contracts or upgradeable designs where you need to preserve the original sender's context.
Q2: Why is CALLCODE deprecated?
A: It doesn't preserve msg.sender consistency, which can cause security issues. DELEGATECALL is the safer alternative.
Q3: Can STATICCALL modify state?
A: No. It enforces read-only operations and reverts on state modification attempts.
Q4: What's the gas cost difference between these methods?
A: CALL and DELEGATECALL incur higher costs due to state changes, while STATICCALL is cheaper for read-only operations.