Component: CyberCorp round and deal manager system
Description
The CyberCorp system is built around two main flows that share the same escrow backbone: fundraising rounds and one-off deals. Both rely on LexScroWLite, the core escrow engine that handles payment intake, state transitions, fee distribution, and asset delivery.
This is a brief overview of aspects of the escrow engine (LexScroWLite).
It controls the full life cycle of an agreement through clear states:
PENDING→PAID→FINALIZEDorVOIDED.The
handleCounterPartyPaymentpulls buyer assets (ERC-20/721/1155) into escrow and marks it as paid.The
finalizeEscrowfunction first updates the status toFINALIZEDthen sends ERC-20 tokens tocompanyPayableand fees togetPlatformPayable. Corp assets (certificates) go to the escrow's counterparty.The
voidAndRefundsafely reverses the flow by setting the status toVOIDEDbefore refunding buyer assets.Conditions are enforced through
conditionCheck, looping through each attached ICondition contract and requiring all to pass.Reentrancy protection and strict ordering (state update before external calls) make double-spends and recursive refunds impossible.
This is a brief overview of aspects of RoundManager.
It manages multi-investor fundraising rounds.
Rounds are created via
createRound, which requires a valid EIP-712 signature from an authorized officer (_verifyEscrowedSignature) binding all parameters — pricing, caps, time window, token, and corp address.Investors submit EOIs through
submitEOI, which validates timing and ticket size, records escrow data, and pulls payment immediately. For FCFS rounds, allocation is triggered automatically.The
allocatefunction enforces round validity, EOI freshness, cap limits, and correct status (PAID, not already allocated). It calculates the eligible allocation, refunds any excess payment, and finalizes escrow to transfer funds and certificates.Both
rejectandrecallEOIhandle refunds, requiring the escrow to be paid and unallocated before returning funds and voiding the record.Fees are computed with
computeFee(size)using a factory-defined ratio capped at 100% (BASIS_POINTS= 10,000).Upgrades are restricted so that only the factory's reference implementation can be approved.
This is a brief overview of aspects of DealManager.
It handles single deals with a similar escrow flow.
The
proposeDealcreates a contract in the registry, mints certificates via the issuance manager, and sets up the escrow with one ERC-20 asset flagged for fees.Both
signDealAndPayandsignAndFinalizeDealprocess signatures and payments then update the escrow's counterparty, pull funds, and optionally finalize the agreement.There is a known issue. These functions use
updateEscrow(..., msg.sender, ...), meaning whoever submits the transaction becomes the counterparty. This opens a front-running vector where a relayer can finalize a deal with a valid signer's signature and receive the certificates. The attacker pays but gains ownership — so it is not a drain but still a logic flaw. The fix is to bind the counterparty to thesigneror include the beneficiary in the signer's authorization as stated in finding 3.2.Deals can be finalized, voided, or refunded under strict conditions (e.g.,
status == PAID, not expired, all signatures complete).Governance, fee logic, and upgrade restrictions mirror those in RoundManager.
The factories (RoundManagerFactory and DealManagerFactory) do the following:
Deploy new managers deterministically using
CREATE2with the ERC-1967 proxy patternEnforce that upgrades can only target the current reference implementation
Restrict admin actions (fee ratio, payable address, reference impl) to the owner, with fee ratios capped at 100%
Invariants
Escrow states are one-way and irreversible:
PENDING→PAID→FINALIZED/VOIDED.Refunds can only occur once since refund functions require
status == PAIDand immediately mark the escrow asVOIDED.Finalization only occurs when the deal is not expired, all parties have signed, and all attached conditions pass.
Payment flow is deterministic.
Company funds always go to
companyPayable.Platform fees always go to
getPlatformPayable.No other addresses can receive escrowed funds.
Fees are bounded and safe.
Factories prevent ratios above 100%.
Checked arithmetic prevents overflow or underflow.
Only buyer tokens marked
isFee == truehave fees deducted.
Round allocations are capped and consistent.
Respect investor deposit and min/max ticket, and raise cap.
Overdeposits are refunded before finalization.
The storage layer must update
escrow.buyerAssets[0].amountafter refunds to align with what is left to finalize (otherwise the transaction reverts but does not misdirect funds).
Reject and recall flows.
Only valid if escrow is paid and unallocated.
Always void before refunding.
All rounds require a verified EIP-712 signature from an authorized officer.
Upgrades are gated to reference implementations via factory control.
Refund tokens always match the payment token in the escrow (enforced in storage).
Test coverage
RoundManager tests cover round creation, EIP-712 signature validation, EOI submission, allocation logic, cap enforcement, refunds, fee behavior, LexChex KYC checks, and upgrade permissions.
DealManager tests go through end-to-end flows: proposal, signing, payment, finalization, voiding, and refunding — plus reverts for invalid signatures or deal states.
Factories are tested for proper
CREATE2deployment, deterministic address calculation, admin access control, and enforcement of fee-ratio limits and upgrade restrictions.CyberCorp integration tests confirm certificate issuance, LexChex condition enforcement, registry signing, secret handling, transfer hooks, and other cross-contract interactions.
The current suite provides broad coverage of the intended flows, fund movements, and access control. What is missing is a negative case for the signer/beneficiary confusion: testing a scenario where
msg.senderdiffers from thesignerbut still succeeds. Adding this test would highlight the vulnerability in finding 3.2 and confirm the fix once implemented.
Attack surface
The following outlines potential attack vectors through which adversaries could attempt to exploit the system. These represent surface-level entry points for adversarial behavior rather than identified vulnerabilities.
Relayer signature theft
Attackers can steal valid signatures from the mempool and front-run legitimate transactions in the deal-signing flows. By submitting the transaction first with a stolen signature, the attacker becomes the escrow.counterParty instead of the intended buyer. Certificates and assets get delivered to the attacker while the legitimate signer receives nothing. The attacker must provide payment, but this breaks the KYC chain, steals negotiated deal terms, and redirects ownership.
Factory initialization hijacking
New manager instances are deployed as uninitialized proxies through the factory system. Anyone monitoring the mempool can front-run the deployment and claim ownership by calling initialize() first with their own malicious auth contract. This gives complete control over the manager instance, access to all deals and escrows, and the ability to upgrade to backdoored implementations.
EIP-712 signature replay
Authorized officer signatures used in round creation and agreement signing could be captured and replayed. Without proper nonces and chain-specific bindings, these signatures can be reused across different chains, for different rounds, or after parameter changes. This enables unauthorized round creation, bypassing restrictions and reusing old approvals in unintended contexts.
Centralized control points
A compromised factory owner can push malicious reference implementations that all managers could upgrade to, manipulate fee ratios up to 100%, or redirect fee-payment addresses. Individual manager owners can be socially engineered into upgrading to backdoored code. The finalizer role has privileged powers to void agreements without requiring signatures, creating a centralized trust assumption.