Smart Contract Security

The Hedera Smart Contract Service (HSCS) integrates the features of Hedera's third-generation native entity functionality—high throughput, fast finality, predictable and affordable fees, and fair transaction ordering—with a highly optimized and performant second-generation Ethereum Virtual Machine (EVM). We aim to offer comprehensive support for smart contracts originally written for other EVM-compatible chains and to enable their seamless deployment on Hedera.

EVM Equivalence

We strive to ensure that developers can conveniently point to a Hedera-supported RPC endpoint and perform smart contract executions and queries using the same code and similar tools to achieve EVM equivalence. To realize this objective, all smart contract transactions are executed using the Besu EVM, and the resulting changes are stored in the Hedera-optimized Virtual Merkle Tree state. Users are thus guaranteed deterministic finality (as opposed to probabilistic finality) of smart contract executions within 2-3 seconds while ensuring that state changes are entirely encompassed within smart contract functionality.

Security Model

Old model (v1) boundaries

The old security model (pre 0.35.2) supported account key signatures provided at transaction time for authorization. Some of the key characteristics of this model included:

  • Smart contracts could only change their own storage or the storage they were delegate called with.

  • System smart contracts could be delegate called to carry out Hedera Token Service (HTS) operations on behalf of another account - Externally Owned Account (EOA) or contract account.

  • Smart Contracts could change an EOA’s storage with the appropriate signature in the transaction.

  • Smart Contracts could change an EOA’s balance with the appropriate signature in the transaction or with prior addition to an allowance approval list.

This provided a huge improvement to user experience as contracts could combine transactions in an attempt at atomicity. For instance, a contract could associate, transfer and approve transactions on a user's behalf with one signature. While focusing on usability, this approach did not address cases in which bad actors could carry out an unsanctioned transaction on behalf of a user, e.g., https://hedera.com/blog/analysis-remediation-of-the-precompile-attack-on-the-hedera-network

To address this, the core Hedera engineers thoroughly analyzed the Smart Contract Service and the HTS system contracts, aiming to secure the state and token assets of users and the network during Smart Contract executions. The results of this effort are the guidelines in Hedera Services release v0.35.2.

New model (v2) boundaries

In the new security model, account key signatures cannot provide authorization for contract actions. Its key characteristics include:

  • Smart contracts can only change their own storage or the storage they were delegate called with.

  • System smart contracts may not be delegate called, except from the Token proxy/facade flow, e.g., HIP 719. In such cases, HTS tokens are represented as smart contracts (see HIP 218) for common ERC methods.

  • Smart contracts can change an EOAs storage only if the contract ID is contained in the EOAs key.

  • Smart contracts can change an EOAs balance if approved for a token allowance for a specific token held by the EOA.

Boundary comparison table

Boundary Spec
v1 Model
v2 Model
Change

Storage Changes

Smart Contracts could only change their own storage or the storage they were delegate called with

Smart contracts can only change their own storage or the storage they were delegate called with

N

System Contract Call Types

System smart contracts could be delegate called in order to carry out Hedera Token Service operations on behalf of another account (EOA) or contract.

System smart contracts may not be delegate called, except from the Token facade flow, which presents HTS tokens as smart contracts for common ERC methods.

Y

Permissioned Account Storage Changes

Smart Contracts could change an EOA’s storage with the appropriate signature in the transaction.

Smart contracts can change an EOAs storage if the contract ID is contained in the EOAs key.

Y

Permissioned Account Balance Changes

Smart Contracts could change an accounts (EOA or contract) balance with the appropriate signature in the transaction or with prior addition to an allowance approval list

Smart contracts can change an EOAs balance if they have been approved a token allowance.

Y

In summary, HSCS utilizes a three-level security approach:

  1. Level 0 - EVM Security Model: Entities may only modify their own state and balance.

  2. Level 1 - ERC Account Value Security Models: Transfer and access to account value will follow tested web3 interface standards, e.g., ERC20, ERC721.

  3. Level 2 - Hedera Advanced Security Features: Unique Hedera features may utilize contract-compatible permissions, e.g., ContractID keys.

To achieve state change or value transfer, executions must adhere to the rules of each level. Transactions that don’t satisfy the appropriate authorization will fail with response codes such as INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE when a sender is not authorized to carry out an operation. More operational-specific response codes will be returned where applicable e.g. SPENDER_DOES_NOT_HAVE_ALLOWANCE.

Impact on Developers

As a developer on Hedera, what should I do?

Developers are strongly encouraged to test their applications with new contracts and UX using the new security model to avoid unintended consequences.

  • The new security model has been applied to contracts created from the mainnet 0.35.2 release and onwards.

  • Existing contracts deployed before this upgrade will continue to use the previous security model for a limited time to allow for application/UX modifications.

  • The previous security model will only be maintained for approximately three months. The current target is for the network to remove the previous security model and for all contracts to follow the new model by the mainnet release of July 2023.

  • See a comprehensive list of the security updates made here.

What does the change in the security model mean for smart contract developers?

The security update involves changes to entity permissions during contract executions when modifying the state. In short, system contract calls (smart contract calls to the Hedera Token Service) are no longer executed with all upper caller privileges, even if the authorized user provides a signature.

Understanding the process of contract executions for both externally owned accounts (EOAs) and contracts during regular and delegate calls is crucial. This process involves tracking how accounts, state (storage and value balance), and code may change as you progress through the chain of calls.

Before (v1 model)

In a regular call scenario, when a call is made to contract B, B’s code is executed in the context of its own state. This allows B to modify only its own state. The sender value also differs between the calls to highlight that the EOA made the first call and contract A made the second.

After (v2 model)

On the other hand, in a delegate call scenario, the call to contract B sees B’s code executed in the context of A’s state. This allows B to modify A’s state. The sender and recipient values are preserved from the first call as if the EOA initiated the call.

In summary, a delegate call executes the calling contract's code in the context of the previous account, giving the code access to the previous account's state and blurring the lines of authorized state management.

Applying this to the security model changes, the following table summarizes the authorization check changes.

Scenario
Authorization check
Old Model
New Model

Smart contract A can change its own state using a call

sender = Contract A

Y

Y

Smart contract A can change EOA’s state via call

sender = EOA

N

N

Smart contract B can change contract A’s state via call

sender = A

N

N

Smart contract A can change EOA’s state via delegate call

sender = EOA

Y

Y

Smart contract B can change contract A’s state via delegate call

sender = Contract A

Y

Y

System smart contracts can change another accounts (EOA or contract A or contract B) state via call

sender = account

N

N

System smart contract can change another accounts EOA or contract A or contract B) state via delegate call

sender = account

N

N

System contracts can change an accounts (EOA or contact A or contract B) state via call with the appropriate signature

signature map contains signature of accounts (EOA or contact A or contract B respectively)

Y

N

System smart contract can change another accounts (EOA or contact A or contract B) state via delegate call with the appropriate signature

signature map contains signature of accounts (EOA or contact A or contract B)

Y

N

Contract A or B can call a system contract via a call

-

Y

Y

Contract A or B can call a system contract via a delegate call

-

Y

N

At the time of the change, the HTS system contract was the only pathway to expose Hedera API functionality through Smart Contracts. As such, it’s fair to consider the differences between pre and post-security model updates when observing HTS system contract state-changing functions.

Existing HTS system contract impacts summary

IHederaTokenService System Smart Contract Function
v1 Model Authorization Requirements
v2 Model Authorization Requirements
Impacts Code
Solution by Developers

approve, approveNFT

signature map contains accounts admin key signature

msg.sender must be entity to be modified

Y

Upgrade contracts

or

Upgrade DApps to provide explicit user approval

*Additional secure pathways: HIP 376 IERC.approve()

associateToken

signature map contains account admin key signature

msg.sender must be entity to be modified

Y

Upgrade contracts

or

Upgrade DApps to provide explicit user associate

*Additional secure pathways: HIP 719 IHRC.associate()

burnToken

signature map contains token burn key signature

or

Contract Id satisfies Token.supplyKey requirements

Contract Id satisfies Token.supplyKey requirements

Y

Token admin must set desired contract in Supply key

createFungibleToken, createFungibleTokenWithCustomFees, createNonFungibleToken, createNonFungibleTokenWithCustomFees

signature map contains affected account admin key signature(s) in treasury

or

autoRenew assignment case

msg.sender must be entity to be modified in treasury

or

autoRenew assignment case

Y

-

cryptoTransfer

signature map contains sender admin key signature

or

Contract Id satisfies Entity.key requirements

msg.sender must be entity to be modified in treasury

or

autoRenew assignment case

Y

Upgrade DApps to provide explicit user approval.

deleteToken

signature map contains token admin key signature

or

Contract Id satisfies Token.adminKey requirements

Contract Id satisfies Token.adminKey requirements

Y

Token admin must set desired contract in admin key

dissociateToken, dissociateTokens

signature map contains admin key signature

msg.sender must be entity to be modified

Y

Upgrade contracts

or

Upgrade DApps to provide explicit user dissociate

*Additional secure pathways: HIP 719 IHRC.associate()

freezeToken

signature map contains freeze key signature

or

Contract Id satisfies Token.freezeKey requirements

Contract Id satisfies Token.freezeKey requirements

Y

Token admin must set desired contract in freeze key

grantTokenKyc

signature map contains kyc key signature

or

Contract Id satisfies Token.freezeKey requirements

Contract Id satisfies Token.kycKey requirements

Y

Token admin must set desired contract in kyc key

mintToken

signature map contains appropriate signature

or

Contract Id satisfies Token.supplyKey requirements

Contract Id satisfies Token.supplyKey requirements

Y

Token admin must set desired contract in Supply key

pauseToken

signature map contains pause key signature

or

Contract Id satisfies Token.pauseKey requirements

Contract Id satisfies Token.pauseKey requirements

Y

Token admin must set desired contract in pause key

revokeTokenKyc

signature map contains kyc key signature

or

Contract Id satisfies Token.freezeKey requirements

Contract Id satisfies Token.kycKey requirements

Y

Token admin must set desired contract in kyc key

setApprovalForAll

signature map contains admin key signature

msg.sender must be entity to be modified

Y

Upgrade contracts

or

Upgrade DApps to provide explicit user associate

*Additional secure pathways: HIP 376 IERC.setApprovalForAll()

transferFrom, transferFromNFT

signature map contains admin key signature

or

Spender must have been pre-approved an allowance

msg.sender must be entity to be modified in treasury

or

autoRenew assignment case

Y

Upgrade DApps to provide explicit user approval.

transferToken, transferTokens, transferNFT, transferNFTs

signature map contains admin key signature

or

Contract Id satisfies Entity.key requirements

or

Contract has been approved an allowance to spend by owner

msg.sender must be balance owner.

If not 1. Contract Id satisfies Entity.key requirements

or

2. Contract has been approved an allowance to spend by owner

Y

Upgrade DApps to provide explicit user approval.

updateTokenInfo, updateTokenExpiryInfo, updateTokenKeys

signature map contains token admin key signature

or

Contract Id satisfies Token.adminKey requirements

Contract Id satisfies Token.adminKey requirements

Y

Token admin must set desired contract in admin key

wipeTokenAccount, wipeTokenAccountNFT

signature map contains token wipe key signature

or

Contract Id satisfies Token.wipeKey requirements

Contract Id satisfies Token.wipeKey requirements

Y

Token admin must set desired contract in Wipe key

unfreezeToken

signature map contains token freeze key signature

or

Contract Id satisfies Token.freezeKey requirements

Contract Id satisfies Token.freezeKey requirements

Y

Token admin must set desired contract in freeze key

unpauseToken

signature map contains token pause key signature

or

Contract Id satisfies Token.pauseKey requirements

Contract Id satisfies Token.pauseKey requirements

Y

Token admin must set desired contract in pause key

Please note: While the changes impact user experience requiring more explicit steps, it more than proportionately increases user and network security across the board. The team continues to push diligently to provide the community with secure and scalable API solutions to enable them to build creative dApps and carve out their own shared world on the ledger.

Security upgrades:

0.35.2
  • After the security incident on March 9th, the engineers conducted a thorough analysis of the Smart Contract Service and the Hedera Token Service system contracts.

  • As part of this exercise, we did not find any additional vulnerabilities that could result in an attack that that which we witnessed on March 9th.

  • The team also looked for any disparities between the expectations of a typical smart contract developer who is used to working with the Ethereum Virtual Machine (EVM) or ERC token APIs and the behaviors of the Hedera Token Service system contract APIs. Such differences in behavior could be used by a malicious smart contract developer in unexpected ways.

  • In order to eliminate the possibility of these behavioral differences being utilized as attack vectors in the future, the consensus node software will align the behaviors of the Hedera Smart Contract Service token system contracts with those of EVM and typical token APIs such as ERC 20 and ERC 721.

  • As a result, the following changes are made as of the mainnet 0.35.2 release on March 31st:

    • An EOA (externally owned account) will have to provide explicit approval/allowance to a contract if they want the contract to transfer value from their account balance.

    • The behavior of transferFrom system contract will be exactly the same as that of the ERC 20 and ERC 721 spec transferFrom function.

    • For HTS specific token functionality (e.g. Pause, Freeze, or Grant KYC), a contract will be authorized to perform the associated token management function only if the ContractId is listed as a key on the token (i.e. Pause Key, Freeze Key, KYC Key respectively).

    • The transferToken and transferNFT APIs will behave as transfer in ERC20/721 if the caller owns the value being transferred, otherwise it will rely on approve spender allowances from the token owner.

    • The above model will dictate entity (EOA and contracts) permissions during contract executions when modifying state. Contracts will no longer rely on Hedera transaction signature presence, but will instead be in accordance with EVM, ERC and ContractId key models noted.

  • As part of this release, the network will include logic to grandfather in previous contracts.

    • Any contracts created from this release onwards will utilize the stricter security model and as such will not have considerations for top-level signatures on transactions to provide permissions.

    • Existing contracts deployed prior to this upgrade will be automatically grandfathered in and continue to use the old model that was in place prior to this release for a limited time to allow for DApp/UX modification to work with the new security model.

    • The grandfather logic will be maintained for an approximate period of 3 months from this release. In a future release in July 2023, the network will remove the grandfather logic, and all contracts will follow the new security model.

    • Developers are encouraged to test their DApps with new contracts and UX using the new security model to avoid unintended consequences. If any DApp developers fail to modify their applications or upgrade their contracts (as applicable) to adhere to the new security model, they may experience issues in their applications.

Last updated