Security Model

1

Immutable Destination Addresses (Anti-Rugpull)

This is our most important security feature.

When a vault is created, the Withdrawal Address for the Buyer and the Refund Address for the Seller are hardcoded into the blockchain as immutable variables.

Code Evidence (Tscrow.sol):

address public immutable buyerWithdrawAddress;
address public immutable sellerRefundAddress;

constructor(...) {
    // ...
    buyerWithdrawAddress = _buyerWithdrawAddress; // Set once, never changes
    sellerRefundAddress = _sellerRefundAddress;   // Set once, never changes
}
circle-info

What this means: Even if the Admin goes rogue or the Bot is hacked, we cannot steal your funds to our own wallet. The Admin only has the power to choose which of the two addresses (Buyer or Seller) receives the money when a deal is in dispute. They cannot redirect it to a third party.

2

Pull Payments (Anti-Locking)

We never "push" funds to a user automatically during a logic change. We only update the state (e.g., "Money now belongs to Buyer"). The user must then manually call withdraw().

Why?

  • Reentrancy Attacks: Sending tokens triggers code execution on the receiver's side. This is a common attack vector.

  • Denial of Service: If a user deposits from a "blacklisted" address or a contract that reverts transactions, a "Push" system would fail, locking the funds forever. "Pull" ensures the system never gets stuck.

3

Reentrancy Guard

All state-changing functions are protected by OpenZeppelin's nonReentrant modifier.

function withdraw() external nonReentrant {
    // ...
}
4

Predicted Addresses

We use CREATE2 to ensure that the Vault Address you see in the bot is mathematically guaranteed to correspond to the deal details you agreed to. It is impossible for the bot to show you a "valid looking" address that actually points to a malicious contract.

Last updated