Bonding Mechanism
Overview
The bonding mechanism in shMONAD enables users to lock their shMON tokens within specific policies, creating isolated pools of bonded tokens. This mechanism is fundamental to shMONAD's approach to protocol security and MEV optimization.
Bonding tokens into a policy does not generate additional yield beyond the base staking yield. The bonding mechanism primarily serves protocol security and payment guarantee purposes.
Protocol Security
Bonding plays a crucial role in ensuring Monad's security by:
- Aligning validator incentives with network health
- Creating stable, long-term stake commitments
- Enabling performant and cost-efficient validator operations
- Supporting a positive feedback loop of work, rewards, and increased stake
MEV Integration
The bonding system integrates with FastLane's MEV infrastructure:
- Enables validators to participate in productive MEV capture
- Supports integration with FastLane on Monad node software (MFL)
- Facilitates MEV yield distribution through policy mechanics
- Works in conjunction with Atlas EVM for optimized value extraction
Asynchronous Execution Security
Due to Monad's asynchronous execution model, where blocks are built but transaction states are only applied in the subsequent block, the bonding mechanism provides crucial security guarantees:
- Ensures payment finality for protocols like Atlas
- Acts as collateral for cross-block transaction guarantees
- Provides secure state transition during the asynchronous gap
- Enables protocols to enforce payment obligations across block boundaries
Policy-Driven Architecture
This section explains the bonding process, policy management, and associated operations that enable these features through:
- Flexible policy creation and management
- Agent-based operations for advanced functionality
- Secure token management and holds system
- Efficient integration with FastLane's infrastructure
Key Concepts
Policies
A policy in shMONAD represents a set of rules and parameters that govern how tokens can be bonded and unbonded. Each policy:
- Has a unique identifier (
policyID
) - Defines an escrow duration for unbonding
- Can have multiple authorized agents
- Maintains separate accounting for bonded and unbonding tokens
Agents
Policy agents are authorized addresses that can:
- Transfer bonded tokens between accounts
- Execute sponsored transactions using bonded tokens
- Manage policy-specific operations
Policy Management
Creating Policies
Administrators can create new policies using:
function createPolicy(
uint48 escrowDuration
) external returns (uint64 policyID, address policyERC20Wrapper);
Parameters:
escrowDuration
: The mandatory waiting period for unbonding tokens
Returns:
policyID
: Unique identifier for the policypolicyERC20Wrapper
: Address of the ERC20 wrapper contract for this policy
Agent Management
// Add a new agent to a policy
function addPolicyAgent(uint64 policyID, address agent) external;
// Remove an agent from a policy
function removePolicyAgent(uint64 policyID, address agent) external;
// Check if an address is a policy agent
function isPolicyAgent(uint64 policyID, address agent) external view returns (bool);
Bonding Operations
Standard Bonding
To bond tokens into a policy:
function bond(
uint64 policyID,
address bondRecipient,
uint256 amount
) external;
Example:
// Approve shMON transfer
shMON.approve(address(shMonad), amountToBond);
// Bond tokens
shMonad.bond(policyID, recipient, amountToBond);
Combined Operations
For efficiency, users can deposit MON and bond in one transaction:
function depositAndBond(
uint64 policyID,
address bondRecipient,
uint256 amountToBond
) external payable;
Automatic Top-Up Mechanism
The Top-Up mechanism automatically maintains a minimum bonded balance for users, ensuring accounts always have sufficient bonded shares available for policy operations.
Key Benefits
- Operational Continuity: Ensures accounts always have sufficient bonded tokens to cover operations, preventing them from becoming inoperable due to depleted balances
- User-Controlled Automation: Provides configurable limits on automatic rebonding, with isolated settings per policy for fine-grained control
- Enhanced User Experience: Reduces manual intervention needs and optimizes gas usage by intelligently managing token balances
Top-Up Configuration
Users can configure their top-up settings using:
function setMinBondedBalance(
uint64 policyID,
uint128 minBonded,
uint128 maxTopUpPerPeriod,
uint32 topUpPeriodDuration
) external;
Parameters:
policyID
: The policy to set top-up settings forminBonded
: Minimum balance to maintain in bonded statemaxTopUpPerPeriod
: Maximum amount that can be automatically bonded in a periodtopUpPeriodDuration
: Time window controlling top-up frequency (in blocks)
Top-up settings are maintained independently for each policy and user combination. This allows users to have different automatic rebonding behaviors across multiple policies based on their specific requirements for each.
How Top-Up Works
-
Trigger Conditions:
- When a transaction would cause a user's bonded balance to fall below their set
minBonded
threshold - When an operation requires more bonded funds than a user currently has available
- When a transaction would cause a user's bonded balance to fall below their set
-
Automatic Process:
- System calculates how many tokens are needed to restore the minimum balance
- Transfers required tokens from user's unbonded balance to bonded state
- Tracks and limits transfers based on user-defined period settings
-
Rate Limiting:
- Top-ups are capped by
maxTopUpPerPeriod
to prevent unexpected large transfers - Each period (defined by
topUpPeriodDuration
) resets the available top-up amount - Provides predictable and controlled automatic bonding
- Top-ups are capped by
Example
// Set up top-up to maintain at least 100 tokens bonded
// Allow up to 50 tokens to be topped up per 7-day period
shMonad.setMinBondedBalance(
policyID, // Target policy
100 * 10**18, // minBonded
50 * 10**18, // maxTopUpPerPeriod
7 days // topUpPeriodDuration (in blocks)
);
Disabling Top-Up
Users can effectively disable the top-up mechanism by setting appropriate parameters:
// Disable top-up by setting minimum values
shMonad.setMinBondedBalance(
policyID,
0, // No minimum
0, // No automatic top-ups
MIN_TOP_UP_PERIOD_DURATION // Required minimum period
);
Integration with Unbonding
When unbonding tokens, users can update their top-up settings through the newMinBalance
parameter in the unbond function:
function unbond(
uint64 policyID,
uint256 amount,
uint256 newMinBalance
) external returns (uint256 unbondBlock);
Agent Operations
Bonded Token Transfers
Agents can transfer bonded tokens between accounts:
function agentTransferFromBonded(
uint64 policyID,
address from,
address to,
uint256 amount
) external;
Sponsored Transactions
Execute operations using bonded tokens as gas sponsorship:
function agentExecuteWithSponsor(
uint64 policyID,
address account,
address target,
bytes calldata data
) external payable returns (bytes memory);
Security Features
Hold Mechanism
The holds system prevents malicious actions during critical operations:
// Place a hold on bonded tokens
function hold(uint64 policyID, address account, uint256 amount) external;
// Release previously held tokens
function release(uint64 policyID, address account, uint256 amount) external;
View Functions
Monitor policy and account status:
// Get bonded balance
function balanceOfBonded(uint64 policyID, address account) external view returns (uint256);
// Get policy details
function getPolicy(uint64 policyID) external view returns (Policy memory);
// Check hold amount
function getHoldAmount(uint64 policyID, address account) external view returns (uint256);
Integration Examples
Policy Setup and Bonding
// Create a new policy with 7-day escrow
(uint64 policyID, address wrapper) = shMonad.createPolicy(7 days);
// Add an agent
shMonad.addPolicyAgent(policyID, agentAddress);
// Bond tokens
uint256 amount = 1000 * 10**18;
shMonad.bond(policyID, msg.sender, amount);
Agent Operations
// Transfer bonded tokens
shMonad.agentTransferFromBonded(
policyID,
fromAddress,
toAddress,
amount
);
// Execute sponsored transaction
bytes memory result = shMonad.agentExecuteWithSponsor(
policyID,
userAccount,
targetContract,
encodedData
);
Error Handling
Common errors and their solutions:
-
Insufficient Balance
error InsufficientBalance(uint256 available, uint256 required);
- Ensure account has enough unbonded tokens before bonding
- Check for active holds that might restrict available balance
-
Invalid Policy
error InvalidPolicy(uint64 policyID);
- Verify policy exists and is active
- Check policy parameters before operations
-
Unauthorized Agent
error UnauthorizedAgent(uint64 policyID, address agent);
- Ensure agent is properly authorized for the policy
- Verify agent permissions haven't been revoked
Best Practices
-
Policy Creation
- Choose appropriate escrow duration based on use case
- Document policy parameters for users
- Consider gas costs when setting up policies
-
Agent Management
- Implement proper access control for agent operations
- Regularly audit active agents
- Use multi-signature for critical agent operations
-
Bonding Operations
- Validate balances before bonding
- Implement proper error handling
- Consider gas optimization for bulk operations
-
Top-Up Configuration
- Set realistic minimum balances based on policy operations
- Configure periods to match expected usage patterns
- Regularly monitor and adjust top-up parameters as needed