Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/helpers/DelegationMetaSwapAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ contract DelegationMetaSwapAdapter is ExecutionHelper, Ownable2Step {
/// @dev Error thrown when the call is not made by this contract itself.
error NotSelf();

/// @dev Error thrown when msg.sender is not the leaf delegatior.
error NotLeafDelegator();

/// @dev Error thrown when an execution with an unsupported CallType is made.
error UnsupportedCallType(CallType callType);

Expand All @@ -71,7 +74,7 @@ contract DelegationMetaSwapAdapter is ExecutionHelper, Ownable2Step {
/// @dev Error thrown when the input and output tokens are the same.
error InvalidIdenticalTokens();

/// @dev Error thrown when delegations input is an empty array.
/// @dev Error thrown when delegations input is an empty array.
error InvalidEmptyDelegations();

/// @dev Error while transferring the native token to the recipient.
Expand Down Expand Up @@ -134,8 +137,9 @@ contract DelegationMetaSwapAdapter is ExecutionHelper, Ownable2Step {

/**
* @notice Executes a token swap using a delegation and transfers the swapped tokens to the root delegator.
* @dev The msg.sender must be the leaf delegator
* @param _apiData Encoded swap parameters, used by the aggregator.
* @param _delegations Array of Delegation objects containing delegation-specific data.
* @param _delegations Array of Delegation objects containing delegation-specific data, sorted leaf to root.
*/
function swapByDelegation(bytes calldata _apiData, Delegation[] memory _delegations) external {
(string memory aggregatorId_, IERC20 tokenFrom_, IERC20 tokenTo_, uint256 amountFrom_, bytes memory swapData_) =
Expand All @@ -147,6 +151,7 @@ contract DelegationMetaSwapAdapter is ExecutionHelper, Ownable2Step {
if (!isTokenAllowed[tokenFrom_]) revert TokenFromIsNotAllowed(tokenFrom_);
if (!isTokenAllowed[tokenTo_]) revert TokenToIsNotAllowed(tokenTo_);
if (!isAggregatorAllowed[keccak256(abi.encode(aggregatorId_))]) revert AggregatorIdIsNotAllowed(aggregatorId_);
if (_delegations[0].delegator != msg.sender) revert NotLeafDelegator();

// Prepare the call that will be executed internally via onlySelf
bytes memory encodedSwap_ = abi.encodeWithSelector(
Expand Down
22 changes: 22 additions & 0 deletions test/helpers/DelegationMetaSwapAdapter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,28 @@ contract DelegationMetaSwapAdapterMockTest is DelegationMetaSwapAdapterBaseTest
delegationMetaSwapAdapter.swapByDelegation(apiData_, emptyDelegations_);
}

// Test that swapByDelegation reverts when called from a non-leaf delegator
function test_revert_swapByDelegation_nonLeafDelegator() public {
_setUpMockContracts();
bytes memory apiData_ = _encodeApiData(aggregatorId, IERC20(tokenA), amountFrom, swapDataTokenAtoTokenB);
Delegation memory delegation_ = Delegation({
delegate: address(delegationMetaSwapAdapter),
delegator: address(vault.deleGator),
authority: ROOT_AUTHORITY,
caveats: new Caveat[](0),
salt: 0,
signature: hex""
});
delegation_ = signDelegation(vault, delegation_);
Delegation[] memory delegations_ = new Delegation[](1);
delegations_[0] = delegation_;

// Using invalid caller, must be the vault not subVault
vm.prank(address(subVault.deleGator));
vm.expectRevert(DelegationMetaSwapAdapter.NotLeafDelegator.selector);
delegationMetaSwapAdapter.swapByDelegation(apiData_, delegations_);
}

// Test that swapByDelegation reverts if tokenFrom equals tokenTo.
function test_revert_swapByDelegation_identicalTokens() public {
_setUpMockContracts();
Expand Down