147 lines
3.2 KiB
Markdown
147 lines
3.2 KiB
Markdown
# Guard Development Guide
|
|
|
|
## Overview
|
|
|
|
Guards are safety checks that prevent unsafe strategy execution. This guide explains how to create custom guards.
|
|
|
|
## Guard Structure
|
|
|
|
A guard consists of:
|
|
1. Schema definition (in `strategy.schema.ts`)
|
|
2. Evaluation function (in `src/guards/`)
|
|
3. Integration (in `src/planner/guards.ts`)
|
|
|
|
## Creating a Guard
|
|
|
|
### 1. Define Guard Schema
|
|
|
|
Add to `src/strategy.schema.ts`:
|
|
|
|
```typescript
|
|
// Add to GuardSchema type enum
|
|
"customGuard",
|
|
|
|
// Guard params are defined in the guard evaluation function
|
|
```
|
|
|
|
### 2. Create Guard File
|
|
|
|
Create `src/guards/customGuard.ts`:
|
|
|
|
```typescript
|
|
import { Guard } from "../strategy.schema.js";
|
|
|
|
export interface CustomGuardParams {
|
|
threshold: string;
|
|
// Add guard-specific parameters
|
|
}
|
|
|
|
/**
|
|
* Evaluate custom guard
|
|
*
|
|
* @param guard - Guard definition
|
|
* @param context - Execution context
|
|
* @returns Guard evaluation result
|
|
*/
|
|
export function evaluateCustomGuard(
|
|
guard: Guard,
|
|
context: {
|
|
// Add context properties needed for evaluation
|
|
[key: string]: any;
|
|
}
|
|
): { passed: boolean; reason?: string; [key: string]: any } {
|
|
const params = guard.params as CustomGuardParams;
|
|
const threshold = BigInt(params.threshold);
|
|
|
|
// Perform check
|
|
const value = context.value || 0n;
|
|
const passed = value <= threshold;
|
|
|
|
return {
|
|
passed,
|
|
reason: passed ? undefined : `Value ${value} exceeds threshold ${threshold}`,
|
|
value,
|
|
threshold,
|
|
};
|
|
}
|
|
```
|
|
|
|
### 3. Integrate Guard
|
|
|
|
Add to `src/planner/guards.ts`:
|
|
|
|
```typescript
|
|
import { evaluateCustomGuard } from "../guards/customGuard.js";
|
|
|
|
// Add case in evaluateGuard function
|
|
case "customGuard":
|
|
result = evaluateCustomGuard(guard, context);
|
|
break;
|
|
```
|
|
|
|
## Guard Context
|
|
|
|
The context object provides access to:
|
|
- `oracle`: PriceOracle instance
|
|
- `aave`: AaveV3Adapter instance
|
|
- `uniswap`: UniswapV3Adapter instance
|
|
- `gasEstimate`: GasEstimate
|
|
- `chainName`: Chain name
|
|
- Custom properties from execution context
|
|
|
|
## Guard Failure Actions
|
|
|
|
Guards support three failure actions:
|
|
|
|
- `revert`: Stop execution (default)
|
|
- `warn`: Log warning but continue
|
|
- `skip`: Skip the step
|
|
|
|
## Examples
|
|
|
|
### Existing Guards
|
|
|
|
- `oracleSanity.ts`: Price validation
|
|
- `twapSanity.ts`: TWAP price checks
|
|
- `maxGas.ts`: Gas limits
|
|
- `minHealthFactor.ts`: Health factor checks
|
|
- `slippage.ts`: Slippage protection
|
|
- `positionDeltaLimit.ts`: Position size limits
|
|
|
|
## Best Practices
|
|
|
|
1. **Clear Error Messages**: Provide actionable error messages
|
|
2. **Context Validation**: Check required context properties
|
|
3. **Thresholds**: Use configurable thresholds
|
|
4. **Documentation**: Document all parameters
|
|
5. **Testing**: Write comprehensive tests
|
|
|
|
## Testing
|
|
|
|
Create test file `tests/unit/guards/customGuard.test.ts`:
|
|
|
|
```typescript
|
|
import { describe, it, expect } from "vitest";
|
|
import { evaluateCustomGuard } from "../../../src/guards/customGuard.js";
|
|
import { Guard } from "../../../src/strategy.schema.js";
|
|
|
|
describe("Custom Guard", () => {
|
|
it("should pass when value is within threshold", () => {
|
|
const guard: Guard = {
|
|
type: "customGuard",
|
|
params: {
|
|
threshold: "1000000",
|
|
},
|
|
};
|
|
|
|
const context = {
|
|
value: 500000n,
|
|
};
|
|
|
|
const result = evaluateCustomGuard(guard, context);
|
|
expect(result.passed).toBe(true);
|
|
});
|
|
});
|
|
```
|
|
|