Inco charges fees for certain operations to ensure the security and performance of the confidential computing infrastructure. This page explains how fees work and which operations require payment.
Fee Structure
Inco fees are paid in the native blockchain currency (ETH on Ethereum, etc.) and are required for operations that involve processing encrypted inputs from external sources.
Getting the Current Fee Amount
Use the inco.getFee() function to get the current fee amount:
Paying Fees
Fees can be paid in two ways: either by users including them in msg.value, or by having the contract pay from its own ETH balance.
Option 1: User Pays via msg.value
Fees must be paid via msg.value when calling functions that require them. The transaction will revert if insufficient fees are provided.
Option 2: Contract Pays from Balance
Contracts can hold ETH in their balance to pay fees automatically, eliminating the need for users to include fees in msg.value.
Benefits of contract-paid fees:
- Better user experience - no need to calculate or send exact fees
- Simpler function signatures - no
payable modifier required
- Automatic fee management by contract owner
Considerations:
- Contract owner must ensure sufficient ETH balance
- Monitor contract balance and top up as needed
- Consider implementing balance thresholds and alerts
Operations That Require Fees
The following operations create new encrypted handles from external ciphertexts or generate random values. They have a fixed base cost of 0.000001 ETH per call:
| Operation | Fee Required | Description |
|---|
e.newEuint256(bytes memory input) | 1 fee per call | Create a new euint256 from an encrypted input |
e.newEbool(bytes memory input) | 1 fee per call | Create a new ebool from an encrypted input |
e.newEaddress(bytes memory input) | 1 fee per call | Create a new eaddress from an encrypted input |
e.rand() | 1 fee per call | Generate a random euint256 value |
e.randBounded(uint256) | 1 fee per call | Generate a bounded random euint256 value |
e.randBounded(euint256) | 1 fee per call | Generate a bounded random euint256 value |
EList Operations (Dynamic Fees)
Unlike the fixed fees above, most elist operations have a dynamic fee structure that scales with the amount of elements and element type:
or simply
In other words, you pay per bit output by the operation. For euint256 elements (256 bits), this works out to 0.000001 ETH per element.
| Operation | Fee Required | Description |
|---|
e.newEList(...) | ret_len * bits * (0.000001 / 256) ETH | Create a new elist from encrypted inputs |
e.append(list, value) | ret_len * bits * (0.000001 / 256) ETH | Append an element to a list |
e.insert(list, index, value) | ret_len * bits * (0.000001 / 256) ETH | Insert an element into a list |
e.set(list, index, value) | ret_len * bits * (0.000001 / 256) ETH | Set an element at a given index |
e.concat(listA, listB) | ret_len * bits * (0.000001 / 256) ETH | Concatenate two lists |
e.slice(list, start, end) | ret_len * bits * (0.000001 / 256) ETH | Extract a sub-list |
e.sliceLen(list, start, length) | ret_len * bits * (0.000001 / 256) ETH | Extract a sub-list by length |
e.range(start, end, listType) | ret_len * bits * (0.000001 / 256) ETH | Create a list populated with ordered values |
e.reverse(list) | ret_len * bits * (0.000001 / 256) ETH | Reverse the order of elements in a list |
e.shuffle(list) | ret_len * bits * (0.000001 / 256) ETH | Randomly shuffle the elements of a list |
e.shuffledRange(start, end, listType) | 2 * ret_len * bits * (0.000001 / 256) ETH | Create a randomly shuffled list of ordered values |
e.getEuint256(list, index) | Free, only consumes gas. | Read an euint256 element from a list (if allowed) |
e.getEbool(list, index) | Free, only consumes gas. | Read an ebool element from a list (if allowed) |
e.getOr(list, index, default) | Free, only consumes gas. | Read an element or return default (if allowed) |
Example: creating an elist of 52 euint256 elements using range() (a deck of cards) costs 52 × 0.000001 = 0.000052 ETH. Performing further operations on that list, such as shuffle() or reverse(), costs the same amount per call, as they produce new elist with the same length and type.
Users get charged for above eList operations regardless of whether the return handle is allowed or not. Avoid calling them in a for-loop or keep iterations low to avoid excessive fee charges.
Example with user-paid fees:
Example with contract-paid fees:
Multiple encrypted inputs:
Multiple encrypted inputs (contract pays):
Operations That Don’t Require Fees
All other Inco operations are free and don’t require any fee payment:
Math Operations
e.add, e.sub, e.mul, e.div, e.rem
e.and, e.or, e.xor, e.shr, e.shl, e.rotr, e.rotl
Comparison Operations
e.eq, e.ne, e.ge, e.gt, e.le, e.lt
e.min, e.max, e.not
Multiplexer Operations
e.asEuint256(uint256) - Convert known uint256 to euint256
e.asEbool(bool) - Convert known bool to ebool
Access Control
e.allow, e.allowThis, e.isAllowed
Fee Best Practices
For User-Paid Fees
Always Check Fees Before Operations
Calculate Ciphertext Count Accurately
Count each newEuint256, newEbool or newEaddress call in your function to ensure you charge the correct total fee.
For Contract-Paid Fees
Monitor Contract Balance
Implement Balance Management
General Best Practices
Handle Fee Changes
Fees may change over time. Always use inco.getFee() rather than hardcoding fee amounts.
Test Fee Requirements
When testing contracts, ensure sufficient funds for both approaches:
User-Paid Fee Errors
- “Fee Not Paid”: Transaction reverted due to insufficient
msg.value
- Overpaying: While allowed, unnecessary ETH is consumed as gas
- Fee changes: Contract fails if fees increase between deployment and usage
Contract-Paid Fee Errors
- “Insufficient contract balance”: Contract doesn’t have enough ETH to pay fees
- “Below minimum reserve”: Withdrawal attempts that would leave insufficient funds
- “Contract balance depleted”: Functions fail when contract runs out of ETH during high usage
Important: Encrypted input operations (newEuint256, newEbool, newEaddress) require
fees because they involve off-chain decryption and processing within Inco’s
Trusted Execution Environment (TEE). All other operations are performed
symbolically on-chain and are therefore free.