Tutoriel·8 min de lecture·Par Solingo

How to Deploy a Smart Contract on Ethereum — Step by Step

From writing your contract to deploying on mainnet. Using Foundry, Hardhat, or Remix — all methods covered.

# How to Deploy a Smart Contract on Ethereum — Step by Step

Deploying a smart contract is the moment your code becomes immutable reality on the blockchain. It's permanent, public, and unstoppable.

In this guide, we'll walk through three deployment methods—Remix (browser-based), Hardhat (JavaScript), and Foundry (Rust)—from testnet to mainnet, including verification on Etherscan.

Prerequisites

Before deploying, you need:

  • A wallet: MetaMask (browser extension)
  • ETH for gas:
  • - Testnet: Get free Sepolia ETH from faucet

    - Mainnet: Real ETH from an exchange

  • RPC endpoint: Infura, Alchemy, or QuickNode (free tier works)
  • Etherscan API key: For contract verification (free at etherscan.io)
  • Cost estimate:

    • Testnet: Free (faucet ETH)
    • Mainnet: ~$5-50 depending on contract size and gas price

    The Smart Contract We'll Deploy

    We'll use a simple but complete example:

    // SPDX-License-Identifier: MIT
    

    pragma solidity 0.8.20;

    contract SimpleStorage {

    uint256 public storedValue;

    address public owner;

    event ValueUpdated(uint256 newValue, address updatedBy);

    constructor(uint256 _initialValue) {

    storedValue = _initialValue;

    owner = msg.sender;

    }

    function setValue(uint256 _value) public {

    require(msg.sender == owner, "Only owner can update");

    storedValue = _value;

    emit ValueUpdated(_value, msg.sender);

    }

    function getValue() public view returns (uint256) {

    return storedValue;

    }

    }

    Simple, but includes:

    • Constructor with arguments
    • State variables
    • Access control
    • Events
    • View function

    Method 1: Remix (Quickest, No Setup)

    Best for: Beginners, quick tests, learning.

    Step 1: Write the Contract

  • Go to remix.ethereum.org
  • Create SimpleStorage.sol in the contracts folder
  • Paste the code above
  • Step 2: Compile

  • Click the "Solidity Compiler" tab (left sidebar)
  • Select compiler version 0.8.20
  • Click "Compile SimpleStorage.sol"
  • Check for errors (should be green checkmark)
  • Step 3: Connect Wallet

  • Click "Deploy & Run Transactions" tab
  • In "Environment" dropdown, select "Injected Provider - MetaMask"
  • MetaMask will pop up—connect your wallet
  • Ensure you're on the Sepolia testnet in MetaMask
  • Step 4: Deploy

  • In "Contract" dropdown, select SimpleStorage
  • Enter constructor argument: 42 (initial value)
  • Click "Deploy"
  • MetaMask pops up—confirm transaction
  • Wait 10-30 seconds for confirmation
  • Step 5: Verify Deployment

  • Copy the contract address from Remix console
  • Go to sepolia.etherscan.io
  • Paste address—you'll see the contract!
  • Step 6: Interact

    In Remix, under "Deployed Contracts":

    • Click getValue: Returns 42
    • Click setValue, enter 100, transact
    • Click getValue again: Returns 100

    Pros: No installation, visual, instant.

    Cons: Not scriptable, hard to reproduce, no version control.

    ---

    Method 2: Hardhat (JavaScript Ecosystem)

    Best for: Web3 teams, JavaScript developers, existing Node.js projects.

    Step 1: Setup Project

    mkdir simple-storage-hardhat
    

    cd simple-storage-hardhat

    npm init -y

    npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox

    npx hardhat init

    # Select: Create a JavaScript project

    Step 2: Write Contract

    Create contracts/SimpleStorage.sol (same code as above).

    Step 3: Configure Network

    Edit hardhat.config.js:

    require("@nomicfoundation/hardhat-toolbox");
    

    require("dotenv").config();

    module.exports = {

    solidity: "0.8.20",

    networks: {

    sepolia: {

    url: process.env.SEPOLIA_RPC_URL,

    accounts: [process.env.PRIVATE_KEY]

    }

    },

    etherscan: {

    apiKey: process.env.ETHERSCAN_API_KEY

    }

    };

    Create .env:

    SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/YOUR_INFURA_KEY
    

    PRIVATE_KEY=your_wallet_private_key_here

    ETHERSCAN_API_KEY=your_etherscan_api_key

    ⚠️ Never commit .env to git! Add to .gitignore.

    Step 4: Write Deploy Script

    Create scripts/deploy.js:

    const hre = require("hardhat");
    
    

    async function main() {

    const initialValue = 42;

    console.log("Deploying SimpleStorage with initial value:", initialValue);

    const SimpleStorage = await hre.ethers.getContractFactory("SimpleStorage");

    const simpleStorage = await SimpleStorage.deploy(initialValue);

    await simpleStorage.waitForDeployment();

    const address = await simpleStorage.getAddress();

    console.log("SimpleStorage deployed to:", address);

    }

    main().catch((error) => {

    console.error(error);

    process.exitCode = 1;

    });

    Step 5: Deploy to Sepolia

    npx hardhat run scripts/deploy.js --network sepolia

    Output:

    Deploying SimpleStorage with initial value: 42
    

    SimpleStorage deployed to: 0x1234567890AbcdEF1234567890aBcdef12345678

    Step 6: Verify on Etherscan

    npx hardhat verify --network sepolia 0x1234...5678 42

    (Replace address with your deployed address, 42 is constructor arg)

    Pros: Industry standard, great tooling, integrates with npm.

    Cons: Slower than Foundry, JavaScript dependency hell.

    ---

    Method 3: Foundry (Fastest, Most Powerful)

    Best for: Advanced developers, high-performance needs, Solidity-native testing.

    Step 1: Install Foundry

    curl -L https://foundry.paradigm.xyz | bash
    

    foundryup

    Step 2: Create Project

    forge init simple-storage-foundry
    

    cd simple-storage-foundry

    Step 3: Write Contract

    Replace src/Counter.sol with src/SimpleStorage.sol (same code).

    Step 4: Write Test

    Create test/SimpleStorage.t.sol:

    // SPDX-License-Identifier: MIT
    

    pragma solidity 0.8.20;

    import "forge-std/Test.sol";

    import "../src/SimpleStorage.sol";

    contract SimpleStorageTest is Test {

    SimpleStorage public store;

    function setUp() public {

    store = new SimpleStorage(42);

    }

    function testInitialValue() public {

    assertEq(store.getValue(), 42);

    }

    function testSetValue() public {

    store.setValue(100);

    assertEq(store.getValue(), 100);

    }

    function testOnlyOwner() public {

    vm.prank(address(0x123)); // Simulate different caller

    vm.expectRevert("Only owner can update");

    store.setValue(999);

    }

    }

    Run tests:

    forge test -vvv

    Step 5: Configure .env

    SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/YOUR_KEY
    

    PRIVATE_KEY=your_private_key

    ETHERSCAN_API_KEY=your_api_key

    Step 6: Deploy

    source .env
    
    

    forge create src/SimpleStorage.sol:SimpleStorage \

    --rpc-url $SEPOLIA_RPC_URL \

    --private-key $PRIVATE_KEY \

    --constructor-args 42 \

    --verify \

    --etherscan-api-key $ETHERSCAN_API_KEY

    Or use a script (script/Deploy.s.sol):

    // SPDX-License-Identifier: MIT
    

    pragma solidity 0.8.20;

    import "forge-std/Script.sol";

    import "../src/SimpleStorage.sol";

    contract DeployScript is Script {

    function run() external {

    uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");

    vm.startBroadcast(deployerPrivateKey);

    SimpleStorage store = new SimpleStorage(42);

    console.log("Deployed at:", address(store));

    vm.stopBroadcast();

    }

    }

    Deploy with script:

    forge script script/Deploy.s.sol:DeployScript \
    

    --rpc-url $SEPOLIA_RPC_URL \

    --broadcast \

    --verify \

    -vvvv

    Pros: Blazing fast, Solidity-native tests, best tooling.

    Cons: Rust learning curve for contributions.

    ---

    Deploying to Mainnet

    ⚠️ WARNING: Mainnet is permanent and expensive. Triple-check everything.

    Pre-Mainnet Checklist

    • [ ] All tests passing
    • [ ] Security audit (for high-value contracts)
    • [ ] Deployed and tested on Sepolia
    • [ ] Verified on Sepolia Etherscan
    • [ ] Reviewed all constructor arguments
    • [ ] Checked gas estimates (forge inspect SimpleStorage gas)
    • [ ] Funded deployer wallet with ETH (estimate + 20% buffer)
    • [ ] Considered multi-sig ownership for upgrades
    • [ ] Backup of private key (encrypted, offline)

    Mainnet Deployment (Foundry)

    # Setup mainnet RPC
    

    MAINNET_RPC_URL=https://mainnet.infura.io/v3/YOUR_KEY

    # Estimate gas cost

    forge script script/Deploy.s.sol --rpc-url $MAINNET_RPC_URL

    # If cost is acceptable, deploy

    forge script script/Deploy.s.sol \

    --rpc-url $MAINNET_RPC_URL \

    --broadcast \

    --verify \

    -vvvv

    Gas optimization before mainnet:

    forge test --gas-report

    This shows gas usage per function—optimize expensive ones.

    ---

    Common Deployment Mistakes

    1. Wrong Network

    Always check MetaMask network indicator. Mainnet is red, testnets are colored.

    2. Insufficient Gas

    If transaction fails, you still pay gas. Set reasonable gas limit:

    # Estimate first
    

    cast estimate <contract_bytecode> --rpc-url $RPC_URL

    3. Constructor Arguments Encoding

    # Wrong
    

    --constructor-args 42

    # Right (for complex types)

    --constructor-args $(cast abi-encode "constructor(uint256)" 42)

    4. Private Key Exposure

    • Never hardcode private keys
    • Use .env and .gitignore
    • For production, use hardware wallets or Gnosis Safe

    5. Verification Failure

    If Etherscan verification fails:

    # Manual verification
    

    forge verify-contract \

    <CONTRACT_ADDRESS> \

    src/SimpleStorage.sol:SimpleStorage \

    --chain sepolia \

    --constructor-args $(cast abi-encode "constructor(uint256)" 42) \

    --etherscan-api-key $ETHERSCAN_API_KEY

    ---

    After Deployment: Next Steps

  • Verify on Etherscan: Makes source code public, enables UI interaction
  • Test interactions: Call functions via Etherscan "Write Contract" tab
  • Monitor events: Use Etherscan's "Events" tab
  • Set up monitoring: Use Tenderly for alerts
  • Document ABI: Save for frontend integration
  • Transfer ownership: If using multi-sig (e.g., Gnosis Safe)
  • Get Contract ABI

    # Foundry
    

    forge inspect SimpleStorage abi > SimpleStorage.json

    # Hardhat

    npx hardhat compile

    # ABI in artifacts/contracts/SimpleStorage.sol/SimpleStorage.json

    ---

    Testnets vs Mainnet

    | Aspect | Testnet (Sepolia) | Mainnet |

    |--------|-------------------|---------|

    | Cost | Free (faucet) | Real ETH (~$5-50/deploy) |

    | Speed | ~15 sec blocks | ~12 sec blocks |

    | Risk | Zero (fake money) | High (immutable) |

    | Use case | Development, testing | Production |

    Always deploy to testnet first!

    ---

    Deployment Costs (Mainnet)

    Example costs at 30 gwei gas price:

    | Contract Size | Gas Used | Cost (ETH) | Cost (USD @ $2000/ETH) |

    |---------------|----------|------------|------------------------|

    | Tiny (SimpleStorage) | ~200k | 0.006 | $12 |

    | Medium (ERC-20) | ~800k | 0.024 | $48 |

    | Large (NFT + marketplace) | ~2M | 0.06 | $120 |

    Gas optimization = direct cost savings.

    ---

    Conclusion

    You've now deployed a smart contract using three different methods:

    • Remix: Quick, visual, beginner-friendly
    • Hardhat: JavaScript ecosystem, great for web3 teams
    • Foundry: Fastest, most powerful, Solidity-native

    Recommendations:

    • Learning: Use Remix
    • Professional projects: Use Foundry (or Hardhat if JS-heavy)
    • Mainnet: Always test on Sepolia first, get an audit for valuable contracts

    Next steps:

    • Deploy an ERC-20 token
    • Build a frontend with ethers.js or wagmi
    • Explore upgradeable contracts (proxies)

    Your code is now on the blockchain—permanent, transparent, unstoppable. Welcome to Web3. 🚀

    Prêt à mettre en pratique ?

    Applique ces concepts avec des exercices interactifs sur Solingo.

    Commencer gratuitement