Proxy Call
The GeniusProxyCall is a multi-call aggregation contract that enables the execution of complex cross-chain operations, token swaps, and arbitrary contract calls in a single transaction. It serves as the execution engine for the Genius bridge protocol, allowing orchestrators to perform intricate operations like swapping stablecoins for other tokens and executing custom logic on destination chains.
The contract provides a secure and efficient way to bundle multiple operations together, reducing gas costs and improving user experience. It supports token approvals, swaps, transfers, and arbitrary contract calls while maintaining strict access controls and comprehensive error handling.
The GeniusProxyCall contract - overview
The GeniusProxyCall contract is a non-upgradeable contract that implements a comprehensive multi-call system. It allows authorized callers to execute complex sequences of operations including token approvals, swaps, transfers, and arbitrary contract calls in a single transaction.
The contract inherits from MultiSendCallOnly for batch transaction processing and implements AccessControl for secure role management. It provides a flexible interface for orchestrating complex cross-chain operations while maintaining security and efficiency.
The GeniusProxyCall contract - key features
Multi-call aggregation
The contract enables the execution of multiple operations in a single transaction, significantly reducing gas costs and improving efficiency for complex cross-chain operations.
Token approval and execution
Supports automatic token approvals for external contracts, execution of the target operation, and cleanup of approvals to maintain security.
Swap and call operations
Combines token swaps with arbitrary contract calls, allowing for complex operations like swapping stablecoins for other tokens and then executing custom logic.
Native token support
Fully supports native token (ETH) operations alongside ERC20 tokens, providing flexibility for different blockchain networks.
Role-based access control
Implements strict access controls where only authorized callers (orchestrators) can execute operations, preventing unauthorized access and potential exploits.
Comprehensive error handling
Provides detailed error messages and validation for all operations, ensuring reliable execution and clear debugging.
Batch operations
Supports batch processing of multiple tokens and operations, enabling efficient handling of complex scenarios.
Security-first design
Implements security best practices including contract validation, approval cleanup, and safe token transfers.
Understanding the workflow of GeniusProxyCall
Authorization: Only addresses with CALLER_ROLE or the contract itself can execute operations.
Operation Execution: The contract supports various operation types:
Simple contract calls via
execute()
Complex swap and call operations via
call()
Token approval and execution via
approveTokenExecute()
Batch token operations via
approveTokensAndExecute()
Token Management: The contract handles token approvals, transfers, and balance management automatically.
Result Processing: Operations return execution results, effective token addresses, and amounts for further processing.
Cleanup: Approvals are automatically cleaned up after execution to maintain security.
Core functions and their purposes
Complex Swap and Call Operations
function call(
address receiver,
address swapTarget,
address callTarget,
address stablecoin,
address tokenOut,
uint256 minAmountOut,
bytes calldata swapData,
bytes calldata callData
)
external
override
onlyCallerOrSelf
returns (
address effectiveTokenOut,
uint256 effectiveAmountOut,
bool success
)
{
bool isSwap = swapTarget != address(0);
bool isCall = callTarget != address(0);
uint256 stablecoinBalance = IERC20(stablecoin).balanceOf(address(this));
effectiveAmountOut = stablecoinBalance;
effectiveTokenOut = stablecoin;
success = true;
if (isSwap) {
bytes memory wrappedSwapData = abi.encodeWithSelector(
IGeniusProxyCall.approveTokenExecuteAndVerify.selector,
stablecoin,
swapTarget,
swapData,
tokenOut,
minAmountOut,
isCall ? address(this) : receiver
);
bytes memory returnData;
(success, returnData) = address(this).call(wrappedSwapData);
if (success) {
effectiveTokenOut = tokenOut;
effectiveAmountOut = abi.decode(returnData, (uint256));
} else {
IERC20(stablecoin).safeTransfer(receiver, stablecoinBalance);
return (stablecoin, stablecoinBalance, success);
}
}
if (isCall) {
bytes memory wrappedCallData = abi.encodeWithSelector(
IGeniusProxyCall.transferTokenAndExecute.selector,
tokenOut,
callTarget,
callData
);
(success, ) = address(this).call{value: address(this).balance}(
wrappedCallData
);
}
// Transfer final balances to receiver
if (effectiveTokenOut != NATIVE_TOKEN) {
uint256 balance = IERC20(effectiveTokenOut).balanceOf(address(this));
if (balance != 0)
IERC20(effectiveTokenOut).safeTransfer(receiver, balance);
}
return (effectiveTokenOut, effectiveAmountOut, success);
}
Token Approval and Execution with Verification
function approveTokenExecuteAndVerify(
address token,
address target,
bytes calldata data,
address tokenOut,
uint256 minAmountOut,
address expectedTokenReceiver
) external payable override onlyCallerOrSelf returns (uint256) {
uint256 balancePreSwap;
uint256 balancePostSwap;
bool isNativeOut = tokenOut == NATIVE_TOKEN;
if (isNativeOut) {
balancePreSwap = address(expectedTokenReceiver).balance;
_approveTokenAndExecute(token, target, data);
balancePostSwap = address(expectedTokenReceiver).balance;
} else {
balancePreSwap = IERC20(tokenOut).balanceOf(expectedTokenReceiver);
_approveTokenAndExecute(token, target, data);
balancePostSwap = IERC20(tokenOut).balanceOf(expectedTokenReceiver);
}
uint256 amountOut = balancePostSwap - balancePreSwap;
if (amountOut < minAmountOut)
revert GeniusErrors.InvalidAmountOut(amountOut, minAmountOut);
else return amountOut;
}
Batch Token Operations
function _approveAddressAndExecute(
address[] memory tokens,
address target,
bytes calldata data,
address toApprove
) internal {
if (target == address(0)) revert GeniusErrors.NonAddress0();
if (!_isContract(target)) revert GeniusErrors.TargetIsNotContract();
if (!_isContract(toApprove))
revert GeniusErrors.ApprovalTargetIsNotContract();
if (target == address(this)) {
(bool _success, ) = target.call{value: msg.value}(data);
if (!_success) revert GeniusErrors.ExternalCallFailed(target);
} else {
uint256 tokensLength = tokens.length;
for (uint256 i; i < tokensLength; i++) {
IERC20(tokens[i]).approve(toApprove, type(uint256).max);
}
(bool _success, ) = target.call{value: msg.value}(data);
if (!_success) revert GeniusErrors.ExternalCallFailed(target);
for (uint i; i < tokensLength; i++) {
IERC20(tokens[i]).approve(toApprove, 0);
}
}
}
Simple Contract Execution
function execute(
address target,
bytes calldata data
) external payable override onlyCallerOrSelf {
if (target == address(0)) revert GeniusErrors.NonAddress0();
if (!_isContract(target)) revert GeniusErrors.TargetIsNotContract();
(bool _success, ) = target.call{value: msg.value}(data);
if (!_success) revert GeniusErrors.ExternalCallFailed(target);
}
Operation types and use cases
Simple Execution
Purpose: Execute arbitrary contract calls
Use case: Simple operations that don't require token management
Function:
execute()
Swap Operations
Purpose: Swap tokens using external DEX protocols
Use case: Converting stablecoins to other tokens on destination chains
Function:
approveTokenExecuteAndVerify()
Swap and Call
Purpose: Combine token swaps with custom logic execution
Use case: Complex DeFi operations requiring multiple steps
Function:
call()
Batch Operations
Purpose: Execute operations with multiple tokens
Use case: Complex protocols requiring multiple token approvals
Function:
approveTokensAndExecute()
Transfer and Execute
Purpose: Transfer tokens and execute custom logic
Use case: Protocols that require token deposits before execution
Function:
transferTokenAndExecute()
Security features
Access Control
The contract implements strict role-based access control:
Admin: Can manage roles and configuration
Caller: Can execute operations (typically orchestrators)
Self: The contract can call itself for internal operations
Contract Validation
All target addresses are validated to ensure they are actual contracts, preventing calls to EOA addresses.
Approval Management
Token approvals are automatically cleaned up after execution to prevent potential security issues.
Safe Token Transfers
All token transfers use SafeERC20 to prevent common token-related vulnerabilities.
Error Handling
Comprehensive error handling with custom errors provides clear feedback for debugging and monitoring.
Native Token Support
Proper handling of native tokens (ETH) alongside ERC20 tokens with appropriate balance checks.
Integration with other contracts
The GeniusProxyCall interacts with several other contracts in the Genius ecosystem:
GeniusVault: Called by the vault for order execution
DEX Protocols: Various decentralized exchanges for token swaps
DeFi Protocols: External protocols for complex operations
Token Contracts: ERC20 tokens for transfers and approvals
Key state variables
NATIVE_TOKEN
: Constant address representing native tokens (ETH)CALLER_ROLE
: Role identifier for authorized callersDEFAULT_ADMIN_ROLE
: Role identifier for administrators
Events
The contract inherits events from the interfaces and emits various events for operation tracking:
ExternalCallFailed
: When external contract calls failInvalidAmountOut
: When swap output doesn't meet minimum requirementsInvalidCaller
: When unauthorized addresses attempt operationsTargetIsNotContract
: When target address is not a contract
Operation flow examples
Simple Token Swap
User creates order to swap USDC for ETH
Vault calls
call()
with swap target (DEX)Contract approves USDC for DEX
Executes swap on DEX
Verifies minimum output amount
Transfers ETH to receiver
Cleans up approvals
Complex DeFi Operation
User creates order for complex DeFi operation
Vault calls
call()
with both swap and call targetsContract swaps stablecoin for protocol token
Transfers protocol token to DeFi contract
Executes custom logic on DeFi contract
Returns any remaining tokens to receiver
Error handling and validation
Input Validation
Target address must be non-zero
Target must be a contract
Caller must have appropriate role
Token addresses must be valid
Execution Validation
External calls must succeed
Swap outputs must meet minimum requirements
Token transfers must complete successfully
Security Checks
Approvals are cleaned up after use
Native token balances are properly handled
Contract state is validated before operations
The GeniusProxyCall is a critical component of the Genius bridge protocol, providing the execution engine for complex cross-chain operations. Its sophisticated multi-call capabilities, security features, and flexible interface enable the protocol to support a wide range of DeFi operations while maintaining efficiency and security.
Last updated