Quantillon Protocol

QuantillonRebalancerModule

Git Source

Inherits: ReentrancyGuard

Title: QuantillonRebalancerModule

A Safe-owned, non-upgradeable permission to add/remove margin on one position.

No arbitrary execution, transfers, delegatecalls, position entry/exit or bridging. The operator pays gas; USDC always moves between the Safe and HedgerPool's vault. Install only after independent review. Policy changes require a call from the Safe.

Note: security-contact: team@quantillon.money

Constants

safe

address public immutable safe

hedgerPool

IHedgerPool public immutable hedgerPool

usdc

IERC20 public immutable usdc

vault

IQuantillonVault public immutable vault

positionId

uint256 public immutable positionId

State Variables

operator

address public operator

paused

bool public paused = true

limits

Limits public limits

nonce

uint256 public nonce

lastExecution

uint256 public lastExecution

usageDay

uint256 public usageDay

currentDayUsage

uint256 public currentDayUsage

previousDayUsage

uint256 public previousDayUsage

Functions

constructor

constructor(address safe_, address pool_, uint256 positionId_, address operator_, Limits memory limits_) ;

version

Reports this standalone module's release version.

function version() external pure returns (string memory);

configure

Changes the operator and policy; existing usage and cooldown are preserved.

function configure(address operator_, Limits calldata limits_) external nonReentrant;

setPaused

Lets the Safe pause or resume automation without blocking its owner transactions.

function setPaused(bool paused_) external nonReentrant;

addMargin

Adds margin using an exact, atomic Safe approval and preserves its reserve.

Deposits remain possible with an invalid oracle to allow collateral recovery.

function addMargin(uint256 amount, uint256 expectedNonce, uint256 deadline) external nonReentrant;

removeMargin

Removes margin to the Safe, then checks fresh position and protocol solvency atomically.

function removeMargin(uint256 amount, uint256 expectedNonce, uint256 deadline) external nonReentrant;

windowUsage

Conservative rolling-day usage: sum of the current and previous UTC day.

This bounds every rolling 24h period, but can retain usage for almost 48h.

function windowUsage() public view returns (uint256);

_configure

function _configure(address operator_, Limits memory limits_) private;

_authorize

function _authorize(uint256 amount, uint256 expectedNonce, uint256 deadline) private;

_checkWithdrawalFloors

function _checkWithdrawalFloors() private;

_approve

function _approve(uint256 amount) private;

_execute

function _execute(address target, bytes memory data) private returns (bytes memory result);

Events

Configured

event Configured(address indexed operator, Limits limits);

PauseChanged

event PauseChanged(bool paused);

MarginRebalanced

event MarginRebalanced(uint256 indexed nonce, uint256 indexed positionId, bool increase, uint256 amount);

Errors

Unauthorized

error Unauthorized();

InvalidConfiguration

error InvalidConfiguration();

ModulePaused

error ModulePaused();

InvalidRequest

error InvalidRequest();

WrongPositionOwner

error WrongPositionOwner();

DependenciesChanged

error DependenciesChanged();

LimitExceeded

error LimitExceeded();

CooldownActive

error CooldownActive();

InvalidOracle

error InvalidOracle();

PositionFloorBreached

error PositionFloorBreached();

VaultFloorBreached

error VaultFloorBreached();

SafeReserveBreached

error SafeReserveBreached();

SafeExecutionFailed

error SafeExecutionFailed();

TokenOperationFailed

error TokenOperationFailed();

UnexpectedBalanceChange

error UnexpectedBalanceChange();

Structs

Limits

struct Limits {
    uint256 maxActionUsdc;
    uint256 maxWindowUsdc;
    uint256 cooldownSeconds;
    uint256 minSafeReserveUsdc;
    uint256 minMarginBps;
    uint256 marginBufferBps;
    uint256 vaultCrBufferBps;
}