-
-
Notifications
You must be signed in to change notification settings - Fork 85
feat: Add token transformation tracking system for DeFi protocol interactions #156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…ractions - Add TokenTransformationEnforcer to track multiple tokens per delegation - Add AdapterManager to coordinate protocol adapters and update enforcer state - Add AaveAdapter and MorphoAdapter for lending protocol interactions - Add ILendingAdapter interface for protocol adapters - Add comprehensive documentation explaining the system This enables delegations to track token transformations through DeFi protocols, allowing AI agents to use delegated tokens in lending protocols while maintaining granular control over evolving token positions.
| { | ||
| uint256 delegationsLength_ = _delegations.length; | ||
| if (delegationsLength_ == 0) revert InvalidEmptyDelegations(); | ||
| if (_delegations[0].delegator != msg.sender) revert NotLeafDelegator(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Wrong delegate/delegator check prevents authorized users from calling
The check _delegations[0].delegator != msg.sender verifies the wrong field. In a delegation chain, the delegate (recipient of permission) should be the caller, not the delegator (grantor of permission). The DelegationManager.redeemDelegations expects delegations_[0].delegate == msg.sender. This mismatch means the actual authorized delegate cannot call this function, as they would fail this check, while the delegator (who shouldn't be calling) would pass this check but fail in redeemDelegations.
| } | ||
|
|
||
| // Prepare actionData with AdapterManager address for balance measurement | ||
| bytes memory enhancedActionData_ = abi.encode(address(this), _actionData); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: ABI encoding mismatch causes incorrect actionData decoding
AdapterManager encodes action data using abi.encode(address(this), _actionData), which uses dynamic encoding for the bytes parameter (offset + length + data). However, AaveAdapter._handleWithdraw and MorphoAdapter._handleWithdraw decode using abi.decode(_actionData[32:], (address)), assuming flat/packed encoding. With abi.encode, byte position 32 contains the offset pointer, not the underlying token address. This will decode garbage or revert on withdraw operations.
Additional Locations (2)
src/helpers/adapters/AaveAdapter.sol
Outdated
| uint256 wrappedBalanceBefore_ = wrappedToken_.balanceOf(_adapterManager); | ||
|
|
||
| // Wrap the aTokens | ||
| IATokenWrapper(aTokenWrapper).wrap(aTokenAddress_, aTokenAmount_); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Adapter cannot wrap/approve tokens it doesn't hold
In _handleDeposit, after Aave's supply sends aTokens to _adapterManager, the adapter calls aToken_.safeIncreaseAllowance(aTokenWrapper, aTokenAmount_) and IATokenWrapper(aTokenWrapper).wrap(...). However, the adapter contract itself doesn't hold the aTokens - they were sent to _adapterManager. The allowance is set on the adapter's address which has zero balance, causing the wrap operation to fail. The same issue exists in _handleWithdraw where the adapter tries to approve wrapped tokens it doesn't hold.
Additional Locations (1)
src/helpers/adapters/AaveAdapter.sol
Outdated
|
|
||
| // Execute deposit (supply) to Aave on behalf of AdapterManager | ||
| // Note: AdapterManager must have approved Aave Pool before calling this adapter | ||
| IAavePool(aavePool).supply(address(_tokenFrom), _amountFrom, _adapterManager, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Protocol calls fail because adapter lacks input tokens
The AdapterManager holds the input tokens and approves the protocol, but then calls the adapter contract which in turn calls the protocol. When IAavePool(aavePool).supply(...) or IMorphoMarket(...).supply(...) is executed, the protocol attempts to pull tokens from msg.sender (the adapter), not from AdapterManager. Since the adapter doesn't hold the tokens and hasn't approved the protocol, these calls will fail due to insufficient balance or allowance.
Additional Locations (1)
| // For Aave/Morpho, we need to approve the protocol contract | ||
| uint256 currentAllowance_ = _tokenFrom.allowance(address(this), _protocolAddress); | ||
| if (currentAllowance_ < _amountFrom) { | ||
| _tokenFrom.safeIncreaseAllowance(_protocolAddress, type(uint256).max); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Native token input causes revert calling ERC20 methods
When _tokenFrom is address(0) (native token case, which is explicitly handled at line 194-195 for the transfer execution), executeProtocolActionInternal unconditionally calls _tokenFrom.allowance(...) and _tokenFrom.safeIncreaseAllowance(...). Calling these ERC20 methods on address(0) will revert since there's no contract at that address. This makes the native token code path at lines 194-195 unreachable in practice, as the subsequent internal execution will always fail.
…og action string - Removed redundant actionHash parameter from executeProtocolActionByDelegation and related functions - Action hash is now computed internally from the action string in _actionData - Updated ProtocolActionExecuted event to log action as string instead of hash - Added ACTION_DEPOSIT and ACTION_WITHDRAW constants in AaveAdapter - Fixed AdapterManager owner setup in TokenTransformationEnforcer tests
- Create new IAave.sol interface file containing all Aave-related interfaces - Move IAavePool, IAaveDataProvider, IStaticATokenFactory, and IERC4626 interfaces - Update AaveAdapter, AdapterManager, and test files to import from IAave.sol - Centralize Aave interfaces for better maintainability and reuse
…ment - Merge TokenTransformationDesignAnalysis.md into TokenTransformationSystem.md - Integrate design patterns and rationale into architecture sections - Keep contract interaction diagram and design explanations - Remove duplication and cross-references - Single source of truth for system documentation
- Expand abbreviated 'TTE' to full 'TokenTransformationEnforcer' - Clarify validation step description - Make diagram note more readable
| revert InsufficientTokensAvailable(_delegationHash, token_, transferAmount_, available_); | ||
| } | ||
|
|
||
| // Deduct from available amount |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
save a couple units gas by caching new amount vs subtracting twice
| if (currentAllowance_ > 0) { | ||
| _tokenFrom.safeDecreaseAllowance(aavePool, currentAllowance_); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might not need this
| } else if (wrapperAsset_ == address(_tokenFrom)) { | ||
| // Wrapper handles Aave deposit internally | ||
| _tokenFrom.safeIncreaseAllowance(staticATokenAddress_, _amountFrom); | ||
| wrappedShares_ = IERC4626(staticATokenAddress_).deposit(_amountFrom, _adapterManager); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may be able to just deposit to root delegator, ie the user
Overview
This PR introduces a comprehensive token transformation tracking system that enables delegations to track and control token transformations through DeFi protocol interactions (e.g., Aave, Morpho).
Problem Solved
Traditional delegation systems grant access to a fixed amount of a single token. However, when tokens are used in DeFi protocols, they transform into different tokens (e.g., USDC → aUSDC in Aave). This system maintains granular control over all tokens derived from the original delegation until expiration or revocation.
Solution
Components Added
TokenTransformationEnforcer - Tracks multiple tokens per delegationHash
delegationHash => token => availableAmountAdapterManager - Central coordinator for protocol interactions
Protocol Adapters - Protocol-specific implementations
Key Features
Documentation
Comprehensive documentation added in
documents/TokenTransformationSystem.mdexplaining:Testing
TODO: Add comprehensive tests for:
Related Issues
N/A - New feature
Note
Introduce a token transformation tracking system with an enforcer, central AdapterManager, and Aave/Morpho adapters to manage and record delegated asset conversions.
TokenTransformationEnforcer.sol: TracksdelegationHash -> token -> amount, initializes from terms inbeforeHook, validates/deducts transfers, exposesupdateAssetState(restricted toAdapterManager) andgetAvailableAmount.AdapterManager.sol: Orchestrates protocol actions via registeredprotocolAdapters, integrates withDelegationManager.redeemDelegations, manages approvals, executes adapter calls, updates enforcer state, and forwards resulting tokens to the root delegator; supports adapter registration/removal and executor entrypoint.AaveAdapter.sol: Implements deposit/withdraw on Aave; measures balances, wraps/unwraps aTokens viaIATokenWrapper, returnsTransformationInfo.MorphoAdapter.sol: Implements deposit/withdraw on Morpho markets; measures balances and returnsTransformationInfo.ILendingAdapter.soldefiningTransformationInfoandexecuteProtocolAction.documents/TokenTransformationSystem.mddetailing architecture, flows, API, and security.Written by Cursor Bugbot for commit ab9c08d. This will update automatically on new commits. Configure here.