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
23 changes: 9 additions & 14 deletions contracts/evmx/fees/Credit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -121,18 +121,12 @@ abstract contract Credit is FeesManagerStorage, Initializable, Ownable, AppGatew
}

/// @notice Deposits credits and native tokens to a user
/// @param depositTo_ The address to deposit the credits to
/// @param chainSlug_ The chain slug
/// @param token_ The token address
/// @param nativeAmount_ The native amount
/// @param creditAmount_ The credit amount
function deposit(
uint32 chainSlug_,
address token_,
address depositTo_,
uint256 nativeAmount_,
uint256 creditAmount_
) external override onlyWatcher {
/// @param payload_ Encoded deposit parameters: (chainSlug, token, receiver, creditAmount, nativeAmount)
function deposit(bytes calldata payload_) external override onlyWatcher {
// Decode payload: (chainSlug, token, receiver, creditAmount, nativeAmount)
(uint32 chainSlug_, address token_, address depositTo_, uint256 creditAmount_, uint256 nativeAmount_) =
abi.decode(payload_, (uint32, address, address, uint256, uint256));

tokenOnChainBalances[chainSlug_][token_] += creditAmount_ + nativeAmount_;

// Mint tokens to the user
Expand All @@ -142,9 +136,10 @@ abstract contract Credit is FeesManagerStorage, Initializable, Ownable, AppGatew
bool success = feesPool.withdraw(depositTo_, nativeAmount_);

if (!success) {
_mint(depositTo_, creditAmount_);
nativeAmount_ = 0;
// Convert failed native amount to credits
_mint(depositTo_, nativeAmount_);
creditAmount_ += nativeAmount_;
nativeAmount_ = 0;
}
}

Expand Down
8 changes: 1 addition & 7 deletions contracts/evmx/interfaces/IFeesManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,7 @@ pragma solidity ^0.8.21;
import {WriteFinality, AppGatewayApprovals, OverrideParams, Transaction, RawPayload, Payload} from "../../utils/common/Structs.sol";

interface IFeesManager {
function deposit(
uint32 chainSlug_,
address token_,
address depositTo_,
uint256 nativeAmount_,
uint256 creditAmount_
) external;
function deposit(bytes calldata payload_) external;

function wrap(address receiver_) external payable;

Expand Down
3 changes: 2 additions & 1 deletion contracts/evmx/interfaces/IFeesPlug.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ interface IFeesPlug {
address token,
address receiver,
uint256 creditAmount,
uint256 nativeAmount
uint256 nativeAmount,
bytes32 payloadId
);
/// @notice Event emitted when fees are withdrawn
event FeesWithdrawn(address token, address receiver, uint256 amount);
Expand Down
12 changes: 11 additions & 1 deletion contracts/evmx/plugs/FeesPlug.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,17 @@ contract FeesPlug is IFeesPlug, PlugBase, AccessControl {
) internal {
if (!whitelistedTokens[token_]) revert TokenNotWhitelisted(token_);
token_.safeTransferFrom(msg.sender, address(this), creditAmount_ + nativeAmount_);
emit FeesDeposited(token_, receiver_, creditAmount_, nativeAmount_);

// Get chain slug from socket
uint32 chainSlug_ = socket__.chainSlug();

// Encode deposit parameters: (chainSlug, token, receiver, creditAmount, nativeAmount)
bytes memory payload = abi.encode(chainSlug_, token_, receiver_, creditAmount_, nativeAmount_);

// Create trigger via Socket to get unique payloadId
bytes32 payloadId = socket__.sendPayload(payload);

emit FeesDeposited(token_, receiver_, creditAmount_, nativeAmount_, payloadId);
}

/// @notice Withdraws fees
Expand Down
3 changes: 2 additions & 1 deletion test/SetupTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ contract DeploySetup is SetupStore {

// switchboard
switchboard.registerSwitchboard();
switchboard.setEvmxConfig(evmxSlug, 1); // Set EVMX config for trigger payloads
switchboard.grantRole(WATCHER_ROLE, watcherEOA);
switchboard.grantRole(RESCUE_ROLE, address(socketOwner));

Expand Down Expand Up @@ -430,7 +431,7 @@ contract FeesSetup is DeploySetup {
vm.expectEmit(true, true, true, false);
emit Deposited(chainSlug_, address(token), user_, credits_, native_);
hoax(watcherEOA);
feesManager.deposit(chainSlug_, address(token), user_, native_, credits_);
feesManager.deposit(abi.encode(chainSlug_, address(token), user_, native_, credits_));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix critical parameter order mismatch.

The test encodes parameters as (chainSlug_, address(token), user_, native_, credits_) with native_ before credits_, but FeesPlug.sol line 76 encodes as (chainSlug_, token_, receiver_, creditAmount_, nativeAmount_) with creditAmount_ before nativeAmount_. This mismatch will cause the decoder in Credit.sol to assign values to the wrong variables, breaking the deposit flow.

Apply this diff to fix the parameter order:

-        feesManager.deposit(abi.encode(chainSlug_, address(token), user_, native_, credits_));
+        feesManager.deposit(abi.encode(chainSlug_, address(token), user_, credits_, native_));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
feesManager.deposit(abi.encode(chainSlug_, address(token), user_, native_, credits_));
feesManager.deposit(abi.encode(chainSlug_, address(token), user_, credits_, native_));
🤖 Prompt for AI Agents
In test/SetupTest.t.sol around line 434, the abi.encode call passes parameters
as (chainSlug_, address(token), user_, native_, credits_) but FeesPlug.sol
expects (chainSlug_, token_, receiver_, creditAmount_, nativeAmount_); swap the
last two arguments so the call becomes (chainSlug_, address(token), user_,
credits_, native_) to match FeesPlug/Credit.sol decoding and ensure
creditAmount_ and nativeAmount_ map correctly.


assertEq(
feesManager.balanceOf(user_),
Expand Down