Smart contract audit and deployment: Ethereum mainnet turnkey

Logic on mainnet works with user assets: a deployment error is costly and undermines trust. We audit smart contracts, deploy them turnkey, and hand over access along with documentation. The path from finished code to a working contract is shortened many times over, and the class of failures during logic upgrades is closed before launch.

Blockchain Development Services

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1375
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1349
  • B2B Advance company logo design
    B2B Advance company logo design
    794
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1087
  • AIDER company logo development
    AIDER company logo development
    1032
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1129

Smart Contract Deployment: Where It Breaks and What Business Loses

Smart contract deployment to Ethereum mainnet is a one-way operation: once a transaction is confirmed, the code becomes immutable, and no further edits can be made.

Most losses occur not at the moment of publication, but in the logic sent there: an error when deploying code on a testnet looks harmless, but on mainnet it turns into lost assets.

Transaction irreversibility is a property of the network, not a flaw in the tools. A confirmed transaction cannot be rolled back: the only way out is a new contract and migration, if the architecture provides for it at all.

Without an upgrade or emergency stop mechanism, the service owner watches the problem from the sidelines, with no leverage.

Most costly is a vulnerability in logic: overflow in calculations, an order of checks that allows funds to be withdrawn twice, open access to critical functions. The compiler lets this through—it checks syntax, not the author's intent. The cost of an error is withdrawn funds and undermined trust in the product.

A separate point of failure is losing access to the deployment account. The key sits in one place, gets sent in chat, stays with the contractor—and with it go the contract owner's rights.

Below we break down how this is addressed: from preparation and verification to publication with backup management scenarios and a clear migration plan.

Measurable Effect: Release Time, Rollbacks, Failure Class

A managed process is distinguished not by promises but by measurable before-and-after metrics. Below are the areas where the effect of an audit, a well-established build pipeline, and a controlled mainnet launch Ethereum is visible.

Release Time for Updates

The contract is built in the same environment on every iteration, and checks run automatically before the team reviews the changes.

The time from audit completion to code on mainnet shrinks from weeks to days—releasing a version no longer depends on the manual steps of a particular engineer.

Incident Frequency

Each contract receives a set of checks covering logic branches and value boundaries. The share of paths covered by automation grows, and the number of incident reports after launch falls: common errors are cut off before publication, not after.

Service Recovery Time

Roles, release restrictions, and the stop procedure are described in advance. When something goes wrong, returning to the previous state takes minutes instead of hours of coordination—it is clear in advance who performs which action.

Eliminated Failure Class

A whole group of problems is eliminated separately: loss of control, duplicate issuance, mismatch of addresses and access rights. These scenarios are covered by the deployment scheme and testnet checks, so they do not make it to mainnet.

Logic Placement Options: Comparing Approaches

The choice of environment determines who can call the contract, how much state writes cost, and how quickly a transaction becomes irreversible. Below are four options that projects actually choose between, with applicability conditions and limitations for each.

Option When It Fits Limitations
Public mainnet Working with external users, public code verifiability, integration with third-party protocols State writes are paid for in gas, calls are visible to everyone, a logic error cannot be rolled back—only a new version can be released
Testnet and mainnet replica Running migrations and deployment scenarios, testing access rights before release The state does not replicate mainnet, behavior under load and transaction ordering differ—portability is only partially verified
Private network with restricted access Internal accounting between known participants, data does not leave the perimeter No external verifiability, participants confirm trust separately, node and upgrade support falls to us
Layer 2 High-volume user operations where write cost and confirmation speed matter Logic is split across layers, withdrawal of funds to mainnet is added, monitoring and checks become more complex

A testnet is mandatory but does not replace an audit: it catches deployment errors, not errors in the contract's economics.

If the logic works with third-party assets, we put a gradual launch between testnet and mainnet—an address whitelist and an operation volume limit at the start.

How Smart Contract Deployment Works: Stages of Engineering Work

Deployment to mainnet is an irreversible operation: after publication, the contract logic cannot be rewritten; only upgrade mechanisms built in advance can be used. Therefore, we lock the order of work before the first transaction and run it end to end, not in separate steps.

  1. Logic audit. We break down the contract by execution branches: external calls, rights to change parameters, handling of returns. We close findings with fixes and a repeat run—the output is a report with statuses.
  2. Placement scheme. We determine what to publish separately and what to link through a proxy, where libraries live. We lock the transaction order in advance: addresses that later steps depend on are created first.
  3. Setting up access and signers. We separate the administrator, operator, and emergency pause roles across different keys, with critical operations behind a multisig with a confirmation threshold. Keys are not stored in the repository and do not end up in build artifacts.
  4. Testnet verification. We repeat the publication end to end: parameter initialization, role assignment, migrations. We separately run failure scenarios—a call without rights, repeated execution, transaction rollback.
  5. Mainnet publication. Transactions proceed in the approved order with state verification after each one, and we verify the source code in the explorer. We check addresses and hashes before handing them to the team.
  6. Documentation handover. We provide the placement scheme with links, the list of roles and signers, the upgrade and rollback procedure, and the emergency pause policy.

Scope of Documentation and Access Handed Over

We hand over not an archive of files but a working system that your team can develop without us. Each item is checked at acceptance: without it, support quickly turns into attempts to guess how it was set up.

  • Placement configurations — addresses of deployed contracts for each network, initialization parameters, access nodes used, build settings, and source hashes against which compilation was checked.
  • Interaction schemes — call diagrams between contracts, wallets, and external services: who calls whom, which events the backend reads, where the failure points are.
  • Access policies and roles — permission matrix in contracts and on wallets: owner, operator, operation stop, multisig; which actions are available to whom and which signature thresholds are set.
  • Upgrade policy — procedure for releasing a new implementation: preparation, running tests on a network copy, collecting signatures, the application window, and a rollback plan to the previous version.
  • Code documentation — purpose of contracts and functions, supported invariants, known limitations, instructions for local deployment and running checks.
  • Audit report — findings, their closure status, and risks consciously accepted, with the rationale for the decision.
  • Access and keys — transfer of owner rights with rotation: new keys are created on your side, ours are revoked, and the transaction history remains in the public registry.

Acceptance follows a checklist, not “word of mouth”: each item is confirmed by running it—deployment on a network copy, reading events, exercising an upgrade scenario.

Case Study: How We Eliminated a Failure Class During Logic Upgrades

The project was a marketplace with conditional fund storage logic: one contract stored balances, fees, and a dispute queue.

Any update to the fee formula meant manual state migration: accepting requests was stopped for 40 minutes, and after a rollout, discrepancies in balances surfaced once every two to three weeks.

This failure class is unpleasant because the data has already been overwritten—reverting to the previous logic version is not enough.

We separated logic and state: the upgradeable part is built on OpenZeppelin, access to replacing logic is closed behind a multisig wallet with a delay, and the replacement itself is one transaction with a pre-verified rollback procedure.

Before each rollout, dispute and payout scenarios are run on a mainnet copy with real state, and balance discrepancies are automatically compared before and after.

Before and After Metrics

The upgrade window was reduced from 40 minutes to two to three, and rollouts with balance discrepancies stopped—instead of every third one, there are now zero over the entire support period.

Incident response time dropped from 6–8 hours to 15 minutes: investigation no longer starts with manually reading logs; the on-call engineer sees an anomaly in balances and reverts to the previous logic with a single transaction.

Support continues: scheduled releases, balance monitoring, and rebuilding checks for new dispute scenarios.

What to Do If Deployed Logic Is Already Running on Mainnet?

A deployed contract on mainnet is immutable: bytecode written once cannot be rewritten. If logic was not separated into storage and implementation in advance, upgrading deployed logic comes down to releasing at a new address and migrating state.

Hence the rule we state before the first deployment: upgradeability is built into the architecture in advance, not invented after an incident.

A zero-downtime replacement scheme is built on a wrapper contract: users and integrations always interact with a single immutable address, data stays there, and the implementation address changes with one transaction.

The switch happens atomically—either the previous logic or the new logic is active. A “service stopped and waiting” state does not arise, so stopping the service for a scheduled upgrade is not needed and should not be part of the scheme.

Backward compatibility is the main limitation of such a replacement. New code must read already written data in the previous order and with the previous types: shift the field order, and old balances will be read as someone else's.

Therefore, before switching, we verify the storage layout and run the new implementation on a mainnet copy with real account state, not on empty test data.

What must not be done: change the signatures of public methods that external calls already rely on; reuse an address for a different meaning of recorded values; patch one link in a chain of related contracts in isolation—upgrading one breaks the others.

We separately verify that administrative functions are restricted and do not allow replacing the implementation without an agreed procedure.

If upgradeability was not built in from the start, a parallel launch remains: the new version accepts new operations, state is migrated in parts, and calls are switched after reconciling amounts and statuses.

This is more expensive to prepare, but it proceeds without stopping the service and without disruption for users.

Technical Doubts: Answering Engineers' Questions

All five questions below are not about code, but about the procedure around it. That is exactly where projects that are technically written correctly break. We answer as we explain before the start.

Who holds the keys to contract publication?

The deployment key is not stored in the repository, in messages, or on the contractor's machine. It is generated in a hardware signing module that remains with you, and release goes through multisig: no one can withdraw funds or change logic alone.

We record a copy of the recovery phrase in secure storage in advance—loss of access to the contract is irreversible.

How is access differentiated between teams?

We divide roles by least privilege: contract administrator, operator, observer. Accounts are issued for specific actions, and every transaction is logged with the initiator indicated. Change review is possible after the fact and does not depend on who remains on the team.

What is checked before publication?

Static analysis, test coverage of branches with monetary logic, manual review of rights and repeated calls, and a run on a network copy. We separately look at external dependencies: third-party libraries and data sources most often become the hole that is not in your code.

What happens during an incident?

The policy is agreed in advance: who decides on a pause, how the contract is stopped, where the addresses for revoking rights are held. Response is measured in minutes, not hours, so the scheme and access are approved before publication, not when the alarm goes off.

What is included in support after handover?

We hand over source code, the address scheme, the verification report, and upgrade instructions. After that, we stay on support: dependency updates, re-verification before releases, and incident investigation. Describe the task—we will come back with an estimate and a plan.

Let's Discuss the Task: We'll Send an Estimate and Work Plan

To come back with an estimate and work plan, rather than a “from and to” range, we need a minimal set of source data.

We review the contract repository, build artifacts, and network configuration ourselves—you do not need to prepare anything specifically for us; what the team already has is enough.

Then the order is this: clarify what is unclear, lock the scope of checks and the release scheme, and agree on timelines and acceptance points. Below is what we need as input.

  • Repository or addresses of already deployed contracts: we will check the compiler version, dependencies, and entry point.
  • Network and perimeter: mainnet or testnet, confirmation requirements, who holds the deployer key.
  • Roles and access: owner, administrator, pause, contract upgrade—what must remain manageable after launch.
  • Check requirements: share of paths under tests, static analysis, overflows, reentrancy, token issuance rights.
  • Release scheme: order of steps, state migration, rollback to the previous version without data loss.
  • Acceptance: which metrics we consider the result and on which staging environment we verify.
  • Infrastructure: node or network access provider, event monitoring, and alerts after launch.

We confirm receipt within one business day and immediately come back with a list of clarifications. After your answers, we send an estimate and work plan with stages, dependencies, and timelines for each—we discuss the task and start.