Smart contract deployment scripts development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Smart contract deployment scripts development
Simple
~1 business day
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1260
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1170
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    874
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1092
  • image_logo-advance_0.png
    B2B Advance company logo design
    563
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    830

Smart Contract Deployment Scripts Development

One-time deployment via forge create or npx hardhat deploy with hardcoded parameters — this is technical debt. When you need to deploy to 5 chains, then reproduce on testnet for auditors, then repeat in 3 months for a new version — it turns out nobody remembers the exact order of calls, which contracts need initialization after deployment, and on what block verification happened.

Forge Script as Standard

Foundry Script (.s.sol) — Solidity file executed as a deployment script. Key advantage: one language for contracts and deployment, compiler type checking, ability to test the script itself.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {Script, console} from "forge-std/Script.sol";
import {MyProtocol} from "../src/MyProtocol.sol";
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";

contract DeployMyProtocol is Script {
    function run() external {
        uint256 deployerKey = vm.envUint("PRIVATE_KEY");
        address deployer = vm.addr(deployerKey);

        vm.startBroadcast(deployerKey);

        ProxyAdmin admin = new ProxyAdmin(deployer);
        MyProtocol implementation = new MyProtocol();

        bytes memory initData = abi.encodeCall(
            MyProtocol.initialize,
            (vm.envAddress("TREASURY"), vm.envUint("FEE_BPS"))
        );

        TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
            address(implementation),
            address(admin),
            initData
        );

        console.log("ProxyAdmin:", address(admin));
        console.log("Implementation:", address(implementation));
        console.log("Proxy:", address(proxy));

        vm.stopBroadcast();
    }
}

Run: forge script script/DeployMyProtocol.s.sol --rpc-url $RPC --broadcast --verify.

The --verify flag automatically verifies all deployed contracts via Etherscan API. --slow adds a delay between transactions — needed for RPC providers with rate limits.

Parameterization via Environment

No hardcoded addresses in the script. Everything via environment variables:

address treasury = vm.envAddress("TREASURY");
uint256 fee = vm.envUint("FEE_BPS");
bool isMainnet = vm.envBool("IS_MAINNET");

For different environments: files .env.sepolia, .env.mainnet, .env.polygon. The deployment script is the same.

Logging Deployed Contract Addresses

After deployment addresses must be fixed. Approaches:

JSON file via foundry's --json flag. forge script ... --json > deployments/sepolia.json. Structured output with addresses, transaction hashes, block numbers.

Custom logging in script. Via vm.writeJson() and vm.writeFile():

string memory json = vm.serializeAddress("deployment", "proxy", address(proxy));
vm.writeJson(json, string.concat("deployments/", vm.toString(block.chainid), ".json"));

Deployment files are committed to the repository — they serve as the source of truth for frontend, analytics, and future upgrade scripts.

Upgrade Scripts

For UUPS and Transparent Proxy patterns — separate script for each upgrade:

contract UpgradeV2 is Script {
    function run() external {
        address proxy = vm.envAddress("PROXY_ADDRESS");
        address admin = vm.envAddress("PROXY_ADMIN");

        vm.startBroadcast(vm.envUint("PRIVATE_KEY"));
        MyProtocolV2 newImpl = new MyProtocolV2();
        ProxyAdmin(admin).upgradeAndCall(
            ITransparentUpgradeableProxy(proxy),
            address(newImpl),
            ""
        );
        vm.stopBroadcast();
    }
}

Each upgrade script has a name with version (UpgradeToV2.s.sol) and is stored in repository history.

Multi-chain Deployment

Script runs sequentially for each chain:

forge script script/Deploy.s.sol --rpc-url $ETHEREUM_RPC --broadcast --verify
forge script script/Deploy.s.sol --rpc-url $POLYGON_RPC --broadcast --verify --verifier-url $POLYGONSCAN_API
forge script script/Deploy.s.sol --rpc-url $ARBITRUM_RPC --broadcast --verify

Or via Makefile / shell script with iteration over RPC endpoints array.

Timeline

Writing a basic deployment script with parameterization and logging: 1 day. Full deployment infrastructure with upgrade scripts, multi-chain support and CI integration: 2-3 days.

Cost is calculated after clarifying the number of contracts and target networks.