Entrypoints
Each form below maps directly to a contract entrypoint. Filling it in and clicking Call constructs a typed-argv DSOL call. Your wallet shows an approval modal before broadcasting; nothing fires without your explicit click.
place @direct
trigger @direct
Public state
loading…
Contract source Verified
// StopLoss — Phase D of silent-iron-keystone v4.
//
// TWAP-protected conditional sell. User commits to a trigger
// threshold + amount; anyone can call trigger() once the TWAP price
// crosses the threshold. Trigger caller earns a 0.1% bounty.
//
// TWAP source: pool reserves at each block from pool_events. Window
// must be >= 30 blocks (~1 minute) per audit F-06 to defeat
// flash-loan manipulation.
dark contract StopLoss {
public mapping(bytes => bytes) slPool; // order_id → pool_id
public mapping(bytes => uint64) slThreshold; // order_id → threshold price
public mapping(bytes => uint8) slDirection; // order_id → 0=sell-when-below, 1=sell-when-above
public mapping(bytes => uint64) slAmount; // order_id → amount to sell
public mapping(bytes => uint64) slTwapWindow; // order_id → TWAP window blocks
public mapping(bytes => uint64) slExpires; // order_id → expiry block
public mapping(bytes => bool) slExecuted;
public mapping(bytes => bool) triggerNullifiers;
@direct
entry place(bytes order_id, bytes pool_id, uint64 threshold, uint8 direction, uint64 amount, uint64 twap_window, uint64 expires) {
require(slExpires[order_id] == 0, "SL_DUPLICATE");
require(twap_window >= 30, "SL_TWAP_TOO_SHORT");
require(expires > block.number + 100, "SL_EXPIRES_TOO_SOON");
require(amount > 0, "SL_ZERO_AMOUNT");
require(threshold > 0, "SL_ZERO_THRESHOLD");
require(direction <= 1, "SL_BAD_DIRECTION");
slPool[order_id] = pool_id;
slThreshold[order_id] = threshold;
slDirection[order_id] = direction;
slAmount[order_id] = amount;
slTwapWindow[order_id] = twap_window;
slExpires[order_id] = expires;
slExecuted[order_id] = false;
}
// Trigger: caller asserts the TWAP has crossed the threshold. The
// contract trusts the caller's claim subject to the nullifier
// freshness check; the backend's TWAP-validation handler verifies
// the claim against `pool_events` before crediting the trigger.
// If the validation fails, the syscall reverts and the order
// remains unexecuted.
@direct
entry trigger(bytes order_id, bytes nullifier) {
require(slExpires[order_id] != 0, "SL_UNKNOWN");
require(!slExecuted[order_id], "SL_ALREADY_EXECUTED");
require(block.number < slExpires[order_id], "SL_EXPIRED");
require(!triggerNullifiers[nullifier], "SL_REPLAY");
slExecuted[order_id] = true;
triggerNullifiers[nullifier] = true;
syscall(TOKEN_TRANSFER_EMIT_V1, ctx.txHash);
}
}
Download .dsol