Smart Contracts for Sending and Receiving ETH: A Detailed Guide

ยท

Understanding ETH Transactions in Smart Contracts

Smart contracts on the Ethereum blockchain can both send and receive ETH (Ether) natively. This functionality enables a wide range of financial applications without intermediaries. Below we explore four key patterns for handling ETH within contracts.


1. Basic ETH-Receiving Contract

How It Works

Contracts receive ETH through a special payable fallback function. This default function executes when ETH is sent to the contract address without calling a specific method.

pragma solidity ^0.4.24;
contract SimpleReceivingContract {
    function () payable public {} 
    
    function withdrawToOwner(address owner) public {
        selfdestruct(owner); 
    }
}

Key Points:


2. Auto-Refund Contract Pattern

Use Case

When accepting fixed payments (e.g., 1 ETH tickets), automatically refund excess amounts to prevent overpayment.

pragma solidity ^0.4.24;
contract AutoRefund {
    address owner;
    uint256 public constant TICKET_PRICE = 1 ether;

    constructor() public {
        owner = msg.sender;
    }

    function () public payable {
        require(msg.value >= TICKET_PRICE);
        if (msg.value > TICKET_PRICE) {
            uint256 refundAmount = msg.value - TICKET_PRICE;
            msg.sender.transfer(refundAmount);
        }
    }
}

Features:

๐Ÿ‘‰ Explore more Ethereum development patterns


3. Instant Forwarding Contract

Design Pattern

For scenarios requiring immediate fund movement, this contract forwards received ETH to a predefined owner address.

pragma solidity ^0.4.24;
contract ForwardingContract {
    address public owner;

    constructor() public {
        owner = msg.sender;
    }

    function () payable public {
        owner.transfer(msg.value);
    }
}

Advantages:


4. Withdrawal Pattern with Ownership Controls

Secure ETH Management

This pattern implements proper access controls for fund withdrawal, following best practices for contract security.

pragma solidity ^0.4.24;
contract ManagedWithdrawal {
    address public owner;
    uint public balance;

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    constructor() public {
        owner = msg.sender;
    }

    function () public payable {
        balance += msg.value;
    }

    function withdraw() public onlyOwner {
        owner.transfer(balance);
        balance = 0;
    }

    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0));
        owner = newOwner;
    }
}

Security Features:

๐Ÿ‘‰ Learn advanced Solidity security practices


FAQ: ETH Handling in Smart Contracts

Q: Can contracts receive ETH without a payable function?
A: No. The payable modifier is required for any function receiving ETH, including fallback functions.

Q: What's safer - transfer() or send()?
A: transfer() reverts on failure and has gas limits, making it safer than send() which returns false on failure.

Q: How do I handle variable payment amounts?
A: Implement validation logic in your payable function using require() statements.

Q: Can contracts pay other contracts?
A: Yes. Contracts can send ETH to other contracts if they have payable functions.

Q: What happens to ETH sent to destroyed contracts?
A: Funds become unrecoverable. Always withdraw funds before self-destructing.

Q: Why use withdrawal patterns instead of direct transfers?
A: Withdrawal patterns prevent reentrancy attacks and give users control over gas costs.


Key Takeaways

For further reading on Ethereum's financial infrastructure, consult the official Solidity documentation and security guidelines. The patterns shown here form the foundation for more complex DeFi applications.