Voltar para Documentação

Docs Técnicas

Ethereum Adapter

The Ethereum adapter lets any dApp built with ethers.js, viem, wagmi, or web3.js talk to a TREA contract without knowing it's TREA underneath. It speaks the same ABI language that Ethereum established as the industry standard.

O conteúdo abaixo vem das fontes técnicas do repositório e é prerenderizado no site para leitura direta por pessoas, crawlers e agentes.

The Ethereum adapter lets any dApp built with ethers.js, viem, wagmi, or web3.js talk to a TREA contract without knowing it's TREA underneath. It speaks the same ABI language that Ethereum established as the industry standard.

dApp (ethers.js)          AtlasDB node
────────────────          ─────────────────────────────────────
transfer(addr, 1000)  →   POST /api/eth/call/:contract_id
  calldata (hex)      →   decode calldata → ContractArg[]
                      →   ContractInstance::execute(@view)
                      ←   encode return → ABI bytes (hex)
 result (uint256)     ←   { "result": "0000…03e8", "decoded": ["1000"] }

Write calls (@tx) still require a signed ContractCall transaction via POST /api/transaction — the adapter handles read-only calls only. This is by design: signatures in AtlasDB are Ed25519, not Ethereum ECDSA, so write authorization stays inside the AtlasDB trust model.

Endpoints

`GET /api/eth/abi/:artifact_id`

Returns the Ethereum JSON ABI for a published contract artifact.

bash
curl http://localhost:3001/api/eth/abi/basic-token-v1
json
[
  { "type": "function", "name": "balanceOf",
    "inputs": [{ "name": "owner", "type": "address" }],
    "outputs": [{ "name": "", "type": "uint256" }],
    "stateMutability": "view" },
  { "type": "function", "name": "transfer",
    "inputs": [{ "name": "to", "type": "address" }, { "name": "amount", "type": "uint256" }],
    "outputs": [{ "name": "out0", "type": "bool" }],
    "stateMutability": "nonpayable" },
  ...
]

`POST /api/eth/call/:contract_id`

Executes a @view function using raw Ethereum calldata.

Request body:

json
{
  "calldata": "70a08231000000000000000000000000ab...cd",
  "caller": "wallet:alice"
}

| Field | Required | Description | |-------|----------|-------------| | calldata | yes | Hex-encoded Ethereum calldata (4-byte selector + ABI params) | | caller | no | Address injected as ctx.caller in the execution context |

Response (success):

json
{
  "status": "ok",
  "function": "balanceOf",
  "result": "0000000000000000000000000000000000000000000000000000000000002710",
  "decoded": ["10000"]
}

Response (write call rejected):

json
{
  "status": "rejected: function `transfer` is a @tx — write calls must be submitted as a signed ContractCall transaction via POST /api/transaction",
  "error": "..."
}

Using with ethers.js

typescript
import { ethers } from "ethers";

// 1. Fetch the ABI from the node
const res = await fetch("http://localhost:3001/api/eth/abi/basic-token-v1");
const abi = await res.json();

// 2. Encode calldata with ethers.js (no provider needed for encoding)
const iface = new ethers.Interface(abi);
const calldata = iface.encodeFunctionData("balanceOf", [
  "0xab...cd",  // 20-byte address
]);

// 3. Call the adapter
const callRes = await fetch("http://localhost:3001/api/eth/call/my-token-instance", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ calldata, caller: "wallet:alice" }),
});
const { result, decoded } = await callRes.json();

// 4. Decode the return value
const [balance] = iface.decodeFunctionResult("balanceOf", "0x" + result);
console.log("Balance:", balance.toString()); // "10000"

Using with viem

typescript
import { encodeFunctionData, decodeFunctionResult } from "viem";

const calldata = encodeFunctionData({
  abi,
  functionName: "totalSupply",
});

const { result } = await fetch(`/api/eth/call/${contractId}`, {
  method: "POST",
  body: JSON.stringify({ calldata }),
}).then(r => r.json());

const [supply] = decodeFunctionResult({ abi, functionName: "totalSupply", data: `0x${result}` });

Supported ABI types

| Ethereum type | TREA type | |---------------|-----------| | address | Address | | bool | bool | | uint8uint256 | u8u256 | | int64, int128 | i64, i128 | | string | String / AssetId | | bytes32 | Hash256 |

Types not in this table (arrays, tuples, bytes) are not supported and will return a rejected: error. Map and Vector storage fields are internal and not exportable via the Ethereum ABI.

Selector compatibility

The adapter uses keccak256("functionName(type1,type2,...)")[:4] — exactly the same algorithm as Ethereum. The canonical selectors for ERC-20 are:

| Function | Selector | |----------|----------| | transfer(address,uint256) | 0xa9059cbb | | transferFrom(address,address,uint256) | 0x23b872dd | | balanceOf(address) | 0x70a08231 | | approve(address,uint256) | 0x095ea7b3 | | totalSupply() | 0x18160ddd |

Any SDK that generates calldata for ERC-20 functions will automatically match TREA contracts that implement those functions.

Design notes

  • Read-only by design. The adapter only executes @view functions. Write calls

remain inside the AtlasDB signing model (Ed25519 + ContractCall transaction). This is an explicit trust boundary: AtlasDB uses Ed25519, not Ethereum ECDSA. Translating ECDSA-signed writes to Ed25519 is the responsibility of an external bridge or wallet integration — not this adapter.

  • Write calls do produce TREA receipts — via POST /api/transaction with a

signed ContractCall. Any dApp that needs write authorization must go through that path. The adapter's read endpoints are a convenience layer on top of the same TREA runtime, not a bypass of it.

  • Zero-value calls. @view functions do not move value, so zero is a valid

argument (e.g. balanceOf does not take an amount). @tx functions are rejected by the adapter before reaching the runtime. If a write does reach the TREA runtime with a zero amount, it is rejected natively with invalid_amount. No additional zero-value guard is needed in the adapter.

  • No proxy / no EVM. The adapter is a thin translation layer. The execution

happens in the TREA runtime, not in an EVM. All accounting semantics and audit receipts are preserved.

  • Integer range. uint256 and int256 values are capped at u128 / i128

range. Values outside that range return an overflow error. This is intentional — TREA uses u128 as the canonical accounting integer and does not support true 256-bit arithmetic.