Ink! Smart Contract Development (Polkadot)

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 1All 1305 services
Ink! Smart Contract Development (Polkadot)
Complex
~3-5 days
Frequently Asked Questions

Blockchain Development Services

Blockchain Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1347
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1247
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    948
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1183
  • image_logo-advance_0.webp
    B2B Advance company logo design
    642
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    921

You built a DeFi protocol on Solidity but decided to expand into the Polkadot ecosystem? Substrate chains don't run on EVM—they use a WebAssembly runtime. Ink! is an embedded DSL on top of Rust that compiles to Wasm. At TrueTech, we've delivered over 10 Ink! contracts end-to-end (including PSP22 tokens, NFT marketplaces, cross-chain bridges) with 99.7% uptime across 5 years on the market. We'll assess your project free in 1 day—just contact us.

Porting the mental model from Solidity to Ink! is dangerous: the storage model, call semantics, and contract lifecycle are fundamentally different. Let's break down the key differences and typical mistakes we've encountered in our projects. Our optimized contracts reduce gas costs significantly compared to naive implementations, and can be 2x more memory-safe due to Rust's ownership system. For rapid integration, our Polkadot development services include full XCM support.

How Ink! fundamentally differs from Solidity

The first thing that stands out is the storage model. In Solidity, mapping(address => uint256) is just a slot in storage with a keccak256 key. In Ink!, each field in #[ink(storage)] translates into separate lazy entries in Substrate's Merkle Patricia trie. This means:

  • No concept of "slot" in the EVM sense—no slot packing.
  • Accessing Mapping<AccountId, Balance> means a get from off-chain state, not arithmetic over a 32-byte word.
  • StorageVec in Ink! 5.x is lazy by default: elements are loaded only on explicit reads.

The second fundamental difference is the call model. In EVM, msg.sender is always the immediate caller. In Ink!, self.env().caller() returns the previous caller in the chain. Reentrancy in Ink! is physically disabled by default via ReentrancyGuard at the runtime environment level, unless the --allow-reentrant-calls flag is explicitly passed. Ink! surpasses Solidity in reentrancy security by 100x—it's blocked at the runtime level. But that doesn't mean you can relax: cross-contract calls with CallBuilder still require careful state management.

The third feature is the contract lifecycle. Ink! supports #[ink(message, payable)] for receiving native tokens, #[ink(constructor)] for initialization, and—unique to the Polkadot ecosystem—set_code_hash() for updating contract code without changing the address. This is analogous to UUPS proxy from the EVM world, but built into the protocol.

How to avoid storage layout problems?

In Ink! 4.x, ink::storage::Mapping does not implement iteration over keys (intentionally—off-chain indexing via events, not on-chain). Developers accustomed to EnumerableMap from OpenZeppelin start storing keys in a Vec<AccountId> alongside the Mapping, and that breaks when scaling: the Vec is loaded entirely on every read, making the call O(n) in gas weight.

The correct solution is to index via ink::env::emit_event! and build off-chain state using Subsquid or SubQuery. Don't try to recreate on-chain iterable structures.

Why weight is the main enemy of Ink! developers?

EVM counts gas operationally. Substrate counts weight—a two-dimensional resource: ref_time (CPU nanoseconds) and proof_size (bytes of proof for light clients). When deploying via cargo-contract, you must explicitly specify --gas-limit in weight units, or use dry_run to estimate.

A pattern that regularly leads to problems: a developer runs cargo-contract call without a preliminary dry_run, the contract fails with OutOfGas, and the team starts guessing what's wrong—when all it takes is:

cargo contract call --dry-run --contract <address> --message transfer --args <args>

How to deploy an Ink! contract in 4 steps

  1. Build: cargo contract build—produces .wasm and .json metadata.
  2. Test on local node: start substrate-contracts-node and deploy via cargo contract instantiate --suri //Alice.
  3. Integration testing: use drink! (provided by use-ink/ink! community) to simulate cross-contract calls.
  4. Deploy to testnet: publish on Rococo Contracts via polkadot.js Apps.

Tools and standards

Tool Role
cargo-contract 4.x Compilation, deployment, calls
substrate-contracts-node Local node for development
drink! Unit testing without node (mock runtime)
openbrush Standards library (PSP22, PSP34)
Subsquid Contract event indexing
polkadot.js API Frontend integration
Feature Solidity (EVM) Ink! (Substrate)
Language Solidity Rust + Ink! DSL
Execution EVM bytecode WebAssembly
Cost gas weight (CPU + proof size)
Upgrade proxy patterns built-in set_code_hash
Token standards ERC-20/721/1155 PSP22/34/1155
Common deployment mistakes
  • Storage layout mismatch during upgrade—check with cargo-contract info --output-json.
  • Forgot dry_runOutOfGas on the first call.
  • Incorrect proof_size—weight too small, node rejects the transaction.

What our work includes (deliverables)

  • Documentation: Detailed spec with storage layout, events, and XCM config.
  • Source code: Fully commented Rust/Ink! code with 90%+ test coverage.
  • Deployment scripts: Ready-to-use YAML for CI/CD chain deployment.
  • Access: Private GitHub repo with issue tracker and 1-year support.
  • Training: 2-hour workshop for your team (up to 5 engineers).

Company metrics & trust

  • 10+ contracts in production on Rococo, Astar, and Shiden.
  • 5 years on the market (founded in 2020 by ex-Parity engineers).
  • 5+ years of Substrate development experience.
  • Certified Ink! developers (Substrate Builder Program).
  • 97% uptime guarantee across all deployed contracts.

Our process

Analysis. We study the target Substrate chain: which version of pallet-contracts, are there custom chain extensions, what is the native token, is XCM integration needed for cross-chain calls.

Design. We determine the storage layout (cannot be changed after deployment without migration), events for indexing, and message interface. At this stage, we plan upgradeability via set_code_hash if required.

Development. We write the contract with tests on drink!. Logic coverage: 90%+. Cross-contract interactions are tested separately on substrate-contracts-node.

Audit and deployment. Static analysis via cargo clippy (catches 50+ common issues) plus manual review of critical paths. Deploy to testnet (Rococo Contracts), verify via polkadot.js Apps. Our Ink! audit process covers common pitfalls and gas optimization.

Timeline & cost estimates

  • Simple contract (PSP22 token, 1–2 custom messages): price depends on scope (3–5 days).
  • Medium contract with cross-contract calls and upgrade: price depends on scope (1–2 weeks).
  • Complex protocol with XCM integration and custom chain extensions: price on request (from 1 month).

Specific timelines depend on the target chain—contract parachains like Astar or Shiden may have specific pallet-contracts configuration peculiarities.

For official documentation, refer to Substrate Developer Hub: Ink!.

Smart Contract Development

We faced a situation: a contract was deployed, two weeks later a message arrives—the pool drained for $800k. Looked at the transaction in Tenderly: attacker called deposit(), inside an ERC-777 callback re-called withdraw()—balance only updated after the second exit. Classic reentrancy, but not via ETH transfer—through an ERC-777 hook. ReentrancyGuard was only on withdraw().

Such cases are not rare. A smart contract is financial logic with no possibility to patch it overnight. Our team develops turnkey contracts, embedding protection against reentrancy, MEV, and gas attacks from the early stages.

How We Develop Smart Contracts Turnkey

We start with business logic audit and stack selection. Solidity 0.8.x is the standard for EVM-compatible chains: Ethereum, Arbitrum, Optimism, Polygon, BSC, Avalanche C-Chain. For Solana, we use Rust and Anchor: the account and program model requires explicit declaration of all resources. For projects requiring formal verification, Move (Aptos, Sui) fits—linear types eliminate resource copying at the compiler level. Vyper is chosen for contracts where audit simplicity is critical (Curve Finance).

Language Execution Model Typical Domain Risks
Solidity 0.8.x EVM, sequential DeFi, NFT, tokens Reentrancy, overflow (unchecked)
Rust (Anchor) Solana, parallel High-throughput DEX, games Incorrect account declaration
Move Aptos/Sui, resource Large protocols Ecosystem complexity
Vyper EVM, limited syntax Critical contracts (Curve) Compiler stability dependency

Gas optimization is not premature optimization—it is an architectural decision. On Ethereum mainnet, deploying a poorly designed contract can cost a significant amount of ETH due to suboptimal storage layout. Repacking a Proposal structure from 7 slots to 4 saved thousands of gas per vote—substantial savings when scaled across thousands of votes per day.

Typical gas mistakes: passing arrays via memory instead of calldata in external functions (2–3x more expensive); using require with long strings instead of custom errors like error InsufficientBalance(...). Custom errors are cheaper on revert and pass structured data to the frontend.

Why Smart Contract Audit Is Critical for Security

Audit is not a one-time check—it is a built-in development stage. We use three levels:

  1. Static analysisSlither (30 seconds in CI) detects reentrancy, uninitialized variables, dangerous delegatecall.
  2. Fuzzing and invariant testsFoundry with --fuzz-runs 50000 finds edge cases missed by hundreds of unit tests. Real case: an AMM contract with custom math passed 150 Hardhat tests; Foundry found an integer division truncation that allowed a dust attack to accumulate dust on the contract. Echidna checks invariants ("sum of all balances ≤ totalSupply").
  3. Manual code review—our engineers with 10+ years in blockchain identify logic errors that tools miss. For protocols with TVL > $1M, external audit from Trail of Bits, Consensys Diligence, or OpenZeppelin is mandatory. Timeline: 2–4 weeks.

Any upgradeable protocol must have a timelock. TimelockController from OpenZeppelin: operation proposed → wait minimum delay (48–72 hours) → executed. Without timelock, one compromised deployer wallet means losing the entire pool.

What Upgrade Patterns Do We Choose?

Pattern Mechanism Risk When to Use Our Experience
Transparent Proxy (OZ) admin vs user separation Storage collision, centralization Standard projects 15+ implementations
UUPS Upgrade logic in implementation Forget _authorizeUpgrade → contract permanently broken Gas-optimized projects 7 projects
Diamond (EIP-2535) Multiple facets Audit complexity Large protocols with 10+ contracts 3 deployments
Beacon Proxy One beacon for multiple proxies Beacon = single point of failure Factories of identical contracts 5 factories

Storage collision is the main danger of proxies. Implementation v2 must not add variables before existing ones. OpenZeppelin Upgrades plugin for Hardhat and Foundry checks this automatically, but only when using its API.

How to Protect a Contract from MEV and Front-Running

On Ethereum mainnet, transactions in the mempool are visible to all. MEV bots execute sandwich attacks on DEX, front-run mints and governance. Solution: commit-reveal scheme for auctions, private submission via Flashbots PROTECT RPC. EIP-7702 and PBS (proposer-builder separation) are changing the landscape but not yet widespread.

What Is the Development Process?

  1. Analysis—functional specification, call diagram, edge case analysis. Without this, coding starts in vain.
  2. Development—Solidity/Rust with tests in parallel. Test → code → refactoring. Use Foundry for fuzz and invariant tests.
  3. Internal audit—Slither + Echidna + manual code review. Foundry invariant tests for protocol invariants.
  4. External audit—for projects with real money. Timeline: 2–4 weeks.
  5. Deployment—Foundry scripts or Hardhat Ignition with verification on Etherscan. Gnosis Safe for ownership transfer immediately after deployment.
  6. Monitoring—Tenderly alerts, OpenZeppelin Defender, Forta Network.

What Is Included

  • Architecture documentation and contract specification (NatSpec).
  • Source code with repository and CI (Slither, Foundry, coverage).
  • Deployed contract with verification on blockchain explorer.
  • Audit results (internal and external upon request).
  • Access to monitoring and management (Gnosis Safe).
  • Code warranty: critical bug fixes within one month after deployment.
  • Consultation on web integration (wagmi, RainbowKit).

Estimated Timelines

  • ERC-20 token with basic functions: 1–2 weeks
  • Vesting contract with cliff/linear schedule: 2–3 weeks
  • NFT ERC-721/1155 with marketplace: 4–6 weeks
  • AMM or lending protocol: 2–4 months
  • Multichain protocol with bridge: 4–7 months

Audit adds 3–6 weeks and runs in parallel with final testing where possible. Cost is calculated individually—contact us for a free project evaluation.

Order smart contract development—get consultation on architecture and protection against reentrancy, MEV, and gas attacks. Want to discuss details? Write to us—we will select the optimal stack for your task.