PROVEITLocal · 31337

Due-diligence panel

0x8377632F2Df37d0f33beCDCaCd30cb666a1e32cc · chain 31337 · read at block 175 · 2027-10-28 18:06 UTC

Automated checks passed
7 / 8
attention
Failed
1
attention
Require a human
2
human needed
What this panel is worth. Checks 6 and 7 are the ones normally hand-waved, so they are done properly here: a PUSH-aware walk of the deployed bytecode rather than a byte search that would report a delegatecall in a contract that has none, and a real comparison of the deployed runtime code against a local build with constructor immutables masked out. Two rows are marked manual because an RPC call cannot answer them, and the panel says so.

See the donor-facing view of this claim →

The ten checks

01The escrow holds what it still owes
Balance 10,000.00 EURC covers 10,000.00 EURC of outstanding obligations.
PASS

The raw balance on its own only means something before settlement, so this row checks the invariant that has to hold at every block: balance ≥ unsettled tranches + unpaid refunds + bonds in custody. At the moment of the advance, that reduces to the full target.

token.balanceOf(escrow)
10,000.00 EURC
Assigned to the funder
0.00 EURC
Tranches not yet settled
3 · 12,000.00 EURC
Refund pool, unpaid
0.00 EURC
Total contributed
10,000.00 EURC
02The token is a euro stablecoin you recognise
Mock demonstration token EURC. Not a real issuer, on purpose, so nothing here implies we integrated a regulated EMI.
MANUAL

escrow.token() compared against a hard-coded list of euro stablecoin addresses per chain. An address that is not on the list is reported as unknown, never as acceptable.

escrow.token()
0x5FbDB2315678afecb367f032d93F642f64180aa3
Symbol / decimals
EURC / 6
Chain ID
31337
03You are the registered payee
No payee is registered yet. Nothing can be released to anyone.
FAIL

escrow.payee() is read from the chain. The IBAN is stored as a salted commitment, never in the clear, so you confirm it by recomputing keccak256(iban ‖ salt) in your own browser. The panel never sends your preimage anywhere.

escrow.payee()
0x0000000000000000000000000000000000000000
ibanCommitment
0x0000000000000000000000000000000000000000000000000000000000000000
assignedAmount
0.00 EURC
Pledged at
n/a
04The payee cannot be changed
No function in the ABI can reassign the payee, and a live re-registration attempt reverts.
PASS

Two independent tests: an ABI scan for any state-mutating function naming the payee other than the one-time registration, and an eth_call simulation of registerPayee from the payee's own address. Neither depends on trusting the source code.

Functions that write payee
none
Simulated re-registration
not attempted
Note
A funder-signed onward transfer is designed-only. We would rather defend “impossible” than “requires your signature”.
05There is no withdrawal backdoor
18 state-mutating functions, none of them administrative. No owner, no pause, no sweep, no receive, no fallback.
PASS

Every state-mutating entry in the ABI is matched against a list of administrative names, and the set of fund-moving functions is compared against the declared list of movers. ETH is not accepted at all, so a stray transfer is impossible rather than stuck.

Admin-shaped functions found
none
receive / fallback
absent
Functions that move tokens
contribute, withdraw, claimRefund, release, challenge, claimBond, assertOutcome, claimAssertionBond
All state-mutating functions
abortUnpledged, assertOutcome, challenge, claimAssertionBond, claimBond, claimRefund, close, confirmAdvance, contribute, expireUnfunded, finalize, flag, postDischargeReceipt, registerPayee, release, resolveChallenge, submitVerdict, withdraw
06It is not upgradeable and not a proxy
EIP-1967 implementation slot is empty and the deployed code contains no DELEGATECALL.
PASS

eth_getStorageAt on the EIP-1967 implementation slot, plus a PUSH-aware walk of the deployed bytecode. The opcode walk skips PUSHn immediate data; a naive byte search for 0xF4 finds dozens of matches inside constants and would report a delegatecall in a contract that has none.

EIP-1967 impl slot
0x0000000000000000000000000000000000000000000000000000000000000000
DELEGATECALL (0xF4)
0 occurrences
SELFDESTRUCT (0xFF)
0 occurrences
Runtime code size
19648 bytes
07The deployed code is the code in this repository
Byte-for-byte identical to a local build of contracts/AidEscrow.sol, once constructor immutables are masked.
PASS

The runtime bytecode is fetched with eth_getCode and compared against the artifact solc 0.8.24 produces from contracts/AidEscrow.sol. The 24 constructor immutables are written into the runtime code at deployment, so their byte ranges are masked on both sides using solc's immutableReferences map before hashing. On a public chain this is the same comparison Basescan performs for source verification.

keccak256(on-chain code)
0xd3484e26490c9609f3d7275e6b919da58050035036dd1b246a9cfef2614ece0b
keccak256(masked, on-chain)
0x7ce05f769ed742a5927780c14a559d2406b80145c1a99aa211846586179fe209
keccak256(masked, local build)
0x7ce05f769ed742a5927780c14a559d2406b80145c1a99aa211846586179fe209
Immutable ranges masked
91
Compiler
solc 0.8.24, optimizer on, 200 runs, bytecode_hash=none
08The release conditions are the ones represented to you
2-of-3 verifiers, 3 tranches, 1 hour challenge window. Verifier set hash recomputes; the published fee schedule hashes to the on-chain termsHash.
PASS

Everything here is a constructor immutable, so it was fixed before the first euro was contributed. Because the parameters are constructor arguments, they are inside the CREATE2 init-code hash, which means the address itself already commits to them. verifierSetHash is recomputed from verifiers() and threshold(); termsHash is recomputed from the project's published terms: its title, implementer, location, summary, cover photograph hash and fee schedule.

Verifiers
0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 0xBcd4042DE499D14e55001CcbB24a551F3b954096
Threshold
2 of 3
verifierSetHash (on-chain)
0xa461005f714fe8113e5f4d899a347d004b281c1d9ce375e64a2531045d464f2d
verifierSetHash (recomputed)
0xa461005f714fe8113e5f4d899a347d004b281c1d9ce375e64a2531045d464f2d
Dispute panel
0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
Windows
challenge 1 hour · release 1 hour · panel 1 hour
Challenge bond / flag threshold
250.00 EURC / 1,000.00 EURC
conditionsHash
0xe0f475f8749868815c290c8d3d1649e5b1b1fdde34d8ad7d190d89a48ca24745
termsHash
0x8982929238d6cf268353fe0ac30b2e9063baceeadcaf0c8a728aaf42e7a3b5c8 ✓ matches the project's published terms
Tranches
1. 5,000.00 EURC by 2030-05-25 18:05 UTC 2. 4,000.00 EURC by 2030-09-02 18:05 UTC 3. 3,000.00 EURC by 2030-12-11 18:05 UTC
09It is not already assigned to someone else
No payee has ever been registered on this escrow.
PASS

The full PayeeRegistered log from block 0 to head. Double assignment is the classic factoring fraud; here it is structural rather than procedural, which is why check 4 is the one that settles it.

PayeeRegistered events
0
Claim status
FUNDING
advanceRef
not yet confirmed
10The payee is the licensed institution it claims to be
Licence reference on-chain: 0x0000000000000000000000000000000000000000000000000000000000000000. Check it against the supervisor's public register yourself.
MANUAL

This check cannot be automated. The contract stores whatever reference the payee wrote; whether that reference is real, current and belongs to the address you are looking at is a question for the Banco de España / EBA register, not for an RPC call.

licenceRef
0x0000000000000000000000000000000000000000000000000000000000000000
Raw bytes32
0x0000000000000000000000000000000000000000000000000000000000000000
Register
Banco de España, Registro de entidades de dinero electrónico

Locked funds certificate

The same values, in the shape a credit committee files. The chain is the source of truth; this is a convenience, and it is not signed: a signature over it would only tell you that we said it.

Escrow
0x8377632F2Df37d0f33beCDCaCd30cb666a1e32cc
Chain
31337
Status
FUNDING
Token
0x5FbDB2315678afecb367f032d93F642f64180aa3 (EURC, 6 dp)
Target
12,000.00 EURC
Balance
10,000.00 EURC
Total contributed
10,000.00 EURC
Released to payee
0.00 EURC
Refund pool
0.00 EURC
Payee
0x0000000000000000000000000000000000000000
Assigned amount
0.00 EURC
NGO (never a recipient)
0x02484cb50AAC86Eae85610D6f4Bf026f30f6627D
claimId
0x7363686f6f6c2d6c697665000000000000000000000000000000000000000000
conditionsHash
0xe0f475f8749868815c290c8d3d1649e5b1b1fdde34d8ad7d190d89a48ca24745
verifierSetHash
0xa461005f714fe8113e5f4d899a347d004b281c1d9ce375e64a2531045d464f2d
termsHash
0x8982929238d6cf268353fe0ac30b2e9063baceeadcaf0c8a728aaf42e7a3b5c8
Read at block
175