Security model

How the protocol protects funds: contract controls, node attestation, the node network and what to do if you find a bug.

Testnet. The contracts are internally audited. An independent third-party audit is planned for Q2 2027. Read the controls below as implemented and internally reviewed, not independently audited. See Testnet Status.

What exists and what is planned

ControlStatus
Internal security review and testnet testingCurrent
Timelocked upgrades behind a multisigCurrent
Emergency pauseCurrent
Independent third-party auditPlanned for Q2 2027
Formal verification of critical functionsPlanned before mainnet
Bug bounty programPlanned, launches with mainnet (Q4 2027)

Testing so far: 24 of 24 automated tests pass, and fuzzing has run 10,000+ iterations. Findings are on the Audits page.

The path to mainnet: third-party audit in Q2 2027, airdrop in Q3 2027, mainnet in Q4 2027, full DAO governance in Q1 2028.

Contract controls

Upgrades and admin

Today a multisig behind a timelock is the only path that can upgrade the core contracts. See Governance. The delay leaves time to review a queued action and trigger incident response if it is hostile.

Core contracts use the UUPS (Universal Upgradeable Proxy Standard) pattern. The six vaults are EIP-2535 diamonds. Their facets change through diamondCut, which only the vault owner (the MultiSigTimelock) can call.

contract ERC7540VaultBase is
Initializable,
UUPSUpgradeable,
AccessControlUpgradeable,
PausableUpgradeable,
ReentrancyGuardUpgradeable
{
function _authorizeUpgrade(address newImplementation)
internal
override
onlyRole(UPGRADER_ROLE)
{}
}

Roles

All contracts use OpenZeppelin's AccessControlUpgradeable. The holders below are the intended mainnet configuration.

RoleDescriptionHolders (mainnet target)
DEFAULT_ADMIN_ROLECan grant/revoke all rolesMulti-sig (3/5)
ADMIN_ROLEProtocol configurationMulti-sig (3/5)
FULFILLER_ROLEExecute ERC-7540 fulfillmentsValidator nodes
STRATEGY_ROLEExecute strategy operationsOracle nodes
UPGRADER_ROLEUpgrade proxy contractsMulti-sig (3/5)
PAUSER_ROLEEmergency pause2-of-3 Safe (today)

Pause

Any address holding PAUSER_ROLE can pause a contract in an emergency. Today the 2-of-3 Safe holds the role. Pausing by Guardians or by an emergency module is planned and not deployed.

function pause() external onlyRole(PAUSER_ROLE) {
_pause();
emit ProtocolPaused(msg.sender, block.timestamp);
}

Reentrancy and input checks

Every external function that changes state uses the nonReentrant modifier. All user inputs are validated.

function requestDeposit(uint256 assets, address controller, address owner)
external
nonReentrant
returns (uint256)
{
if (assets == 0) revert ZeroAssets();
if (controller == address(0)) revert InvalidController();
if (s.paused) revert E_BREAKER();
if (!(owner == msg.sender || s.isOperator[owner][msg.sender])) revert NotAuthorized();
if (assets < s.minDeposit) revert BelowMinDeposit(); // minDeposit is 0 on all six vaults
// ...
}

ERC-7540 requests

Deposits and redemptions are asynchronous. Four checks protect them:

  1. Request tracking. Each request has a unique ID.
  2. Fulfillment delay. At least 1 hour passes before fulfillment.
  3. Fulfillment. A keeper with FULFILLER_ROLE fulfils requests. VRF based validator selection is planned, not live.
  4. No double fulfillment. Fulfilled requests are tracked onchain.
mapping(uint256 => FulfillmentRequest) public fulfillmentRequests;
mapping(bytes32 => bool) public processedRequests;
function fulfillDeposit(uint256 requestId) external onlyRole(FULFILLER_ROLE) {
FulfillmentRequest storage request = fulfillmentRequests[requestId];
require(!request.fulfilled, "Already fulfilled");
require(block.timestamp >= request.requestTime + fulfillmentDelay, "Delay not passed");
// ...
}

Users can delegate claim operations to an operator:

mapping(address => mapping(address => bool)) public isOperator;
function setOperator(address operator, bool approved) external {
isOperator[msg.sender][operator] = approved;
emit OperatorSet(msg.sender, operator, approved);
}

Node attestation

Offchain results are not trusted at face value. That covers strategy performance, TrustFingerprint updates and reward epochs. The signature, quorum and Merkle proof mechanisms below are implemented and deployed on testnet.

  • Oracle signatures. An oracle key signs each result with ECDSA over the secp256k1 curve, encoded with the EIP-191 personal_sign scheme. The onchain verifier recovers the signer address before it accepts the payload.
  • Registration. Node and AI agent registration uses the same primitive. The server issues a single use, time limited nonce. The operator signs the full message with EIP-191, which binds the wallet to the identity onchain. A captured signature cannot be replayed.
  • BFT quorum. No single oracle can move capital or finalize a result. The consensus contracts require 66% of the oracle signing set to agree before an attestation is final. The quorum counts signing weight, not keys.
  • Merkle reward proofs. Reward distributions are published as a Merkle root, and each operator will claim with a Merkle proof. The MerkleRewardDistributor contract (0xCcDB471823C4F14Ffa4814641eafDa63fb526834 on Base Sepolia) will verify the proof and pay out. Rewards will be transferred from funded reward pools, with no new tokens minted. Rewards are not being paid yet.
  • Hardware attestation. Where a Trusted Platform Module (TPM) or equivalent secure element is available, the node client produces an attestation quote. It is signed with an RSA device key and hashed with SHA-256, which binds the node identity to trusted hardware.
  • Private strategies. Sensitive strategy logic handled by a Guardian or Oracle stays inside a secure enclave. Performance can be published and verified while the strategy stays private.

None of this depends on zero knowledge proofs. Performance privacy comes from secure enclaves and threshold handling, not ZK circuits. Third-party infrastructure named elsewhere in these docs, such as external rollup or data availability providers, is not part of this attestation path.

Node network

Each tier has a job:

  • Oracle: price oracle updates. Planned: ML strategy generation, strategy execution through the ATE and governance proposal creation. Today one protocol keeper submits strategies.
  • Guardian: strategy backtesting (1000+ Monte Carlo simulations), risk assessment and scoring, live strategy monitoring and, once deployed, emergency pause capability.
  • Validator: monitors pending deposit and redeem requests, executes fulfillments when selected by lottery, governance vote execution and data availability.
  • Micro: heartbeat reporting, network health monitoring and data replication.

Network targets are 15–50 Oracle, 25–100 Guardian and 100–1,000 Validator nodes. These are illustrative, not current figures. The initial paid node sale offers 425 nodes in total, and Micro nodes are unmetered. Hardware, stake and rewards are in Node Operators.

TrustFingerprint tracks node behavior. Guardian nodes monitor for threats, and emergency protocols activate automatically when a threat is detected.

The Guardian Chamber is designed to be the protocol's security council, made up of security focused node operators. Its membership and seat counts are set by governance and are being established as the network decentralizes.

Validator selection

Today selection uses keccak(timestamp, prevrandao, nonce). A Chainlink VRF lottery is planned and not live:

function selectValidator(uint256 requestId) internal returns (address) {
// Request random number from Chainlink VRF
uint256 randomWord = vrfCoordinator.requestRandomWords(...);
// Weight by reputation and stake
uint256 totalWeight = getTotalValidatorWeight();
uint256 selection = randomWord % totalWeight;
// Find selected validator
return getValidatorByWeight(selection);
}

Selection for task assignment is weighted by each Validator's fulfillment reputation in ValidatorFulfillmentManager. A successful fulfillment raises it by 1%, a failed one lowers it by 5%. This reputation is separate from the TrustFingerprint score.

Slashing

SlashingManager sets these penalties, as a share of stake:

ViolationValidatorGuardianOracle
Downtime1%2%3%
Poor performance0.5%1%1.5%
Consensus violation15%30%50%
Malicious behavior25%50%75%

Downtime counts after 48 hours without a heartbeat for a Validator, 24 hours for a Guardian and 12 hours for an Oracle.

Staking enforces a minimum stake, and unstaking has a delay. The amounts and the period are in the Staking guide.

// Stake tokens
function stake(uint256 amount) external {
require(amount >= minStake, "Below minimum");
nodrToken.transferFrom(msg.sender, address(this), amount);
stakes[msg.sender] += amount;
emit Staked(msg.sender, amount);
}
// Unstake (with delay)
function unstake(uint256 amount) external {
require(stakes[msg.sender] >= amount, "Insufficient stake");
unstakeRequests[msg.sender] = UnstakeRequest({
amount: amount,
unlockTime: block.timestamp + UNSTAKE_DELAY
});
emit UnstakeRequested(msg.sender, amount);
}

Threats and mitigations

ThreatMitigation
Smart contract vulnerabilitiesInternal review (current), formal verification, third-party audit and bug bounty (all planned)
Node operator fraudTrustFingerprint scoring, slashing, Guardian monitoring
Market manipulationRisk limits, circuit breakers, diversified strategies
Governance attacksTimelocks, quorum requirements, emergency controls
Oracle manipulationMultiple oracle sources, outlier detection, validation

Protect yourself

  1. Verify the official contract addresses before you interact.
  2. Keep significant assets in a hardware wallet.
  3. Review every transaction before you sign.
  4. Watch the official channels for security announcements.

Report a vulnerability

  1. Do not disclose it publicly.
  2. Email [email protected] immediately. A PGP key is available on request.
  3. Include a detailed description, steps to reproduce, the potential impact and a suggested fix if you have one.
  4. Allow reasonable time for remediation.

You can also report through the #security-reports channel in Discord. Reports will be eligible for bug bounty rewards once the program launches.

Next

results matching ""
    No results matching ""