Skip to content

Commit 1594f26

Browse files
committed
Add AutoDeposit contract
1 parent fcd7530 commit 1594f26

File tree

5 files changed

+89
-2
lines changed

5 files changed

+89
-2
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@
2828
[submodule "lib/solidity-cborutils"]
2929
path = lib/solidity-cborutils
3030
url = https://github.com/smartcontractkit/solidity-cborutils
31+
[submodule "lib/ipc"]
32+
path = lib/ipc
33+
url = https://github.com/consensus-shipyard/ipc

lib/ipc

Submodule ipc added at 9616fc9

remappings.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ forge-std/=lib/forge-std/src/
77
@axelar-network/interchain-token-service/=lib/interchain-token-service/
88
@axelar-network/axelar-gmp-sdk-solidity/=lib/axelar-gmp-sdk-solidity/
99
@prb/math/=lib/prb-math/src/
10-
solidity-cborutils/=lib/solidity-cborutils/
10+
solidity-cborutils/=lib/solidity-cborutils/
11+
@ipc/=lib/ipc/

src/token/AutoDeposit.sol

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
pragma solidity ^0.8.26;
3+
4+
import {InterchainTokenExecutable} from "@axelar-network/interchain-token-service/contracts/executable/InterchainTokenExecutable.sol";
5+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6+
import {SubnetID} from "@ipc/contracts/contracts/structs/Subnet.sol";
7+
import {FvmAddress} from "@ipc/contracts/contracts/structs/FvmAddress.sol";
8+
import {IGateway} from "@ipc/contracts/contracts/interfaces/IGateway.sol";
9+
10+
/// @title AutoDeposit
11+
/// @notice Handles automatic token deposits from Axelar to IPC subnets
12+
/// @dev Implements InterchainTokenExecutable for cross-chain token transfers
13+
contract AutoDeposit is InterchainTokenExecutable {
14+
error WrongToken(address received, address expected);
15+
error TokenApprovalFailed(address token, address spender, uint256 amount);
16+
17+
SubnetID public recallSubnet;
18+
IERC20 public immutable RECALL_TOKEN;
19+
IGateway public immutable RECALL_GATEWAY;
20+
21+
/// @notice Initializes the contract with required addresses and subnet ID
22+
/// @param subnet The subnet ID where tokens will be deposited
23+
/// @param token The address of the token to be handled
24+
/// @param gateway The address of the IPC gateway
25+
/// @param interchainTokenService_ The address of Axelar's interchain token service
26+
constructor(
27+
SubnetID memory subnet,
28+
address token,
29+
address gateway,
30+
address interchainTokenService_
31+
) InterchainTokenExecutable(interchainTokenService_) {
32+
recallSubnet = subnet;
33+
RECALL_TOKEN = IERC20(token);
34+
RECALL_GATEWAY = IGateway(gateway);
35+
}
36+
37+
/// @inheritdoc InterchainTokenExecutable
38+
function _executeWithInterchainToken(
39+
bytes32, // commandId
40+
string calldata, // sourceChain
41+
bytes calldata, // sourceAddress
42+
bytes calldata data,
43+
bytes32, // tokenId
44+
address token,
45+
uint256 amount
46+
) internal override {
47+
if (token != address(RECALL_TOKEN)) {
48+
revert WrongToken(token, address(RECALL_TOKEN));
49+
}
50+
51+
bool success = RECALL_TOKEN.approve(address(RECALL_GATEWAY), amount);
52+
if (!success) {
53+
revert TokenApprovalFailed(address(RECALL_TOKEN), address(RECALL_GATEWAY), amount);
54+
}
55+
56+
address recipient = abi.decode(data, (address));
57+
FvmAddress memory fvmAddress = convertToFvmAddr(recipient);
58+
59+
SubnetID memory subnetCopy;
60+
subnetCopy.root = recallSubnet.root;
61+
subnetCopy.route = new address[](recallSubnet.route.length);
62+
for (uint256 i = 0; i < recallSubnet.route.length; i++) {
63+
subnetCopy.route[i] = recallSubnet.route[i];
64+
}
65+
66+
RECALL_GATEWAY.fundWithToken({
67+
subnetId: subnetCopy,
68+
to: fvmAddress,
69+
amount: amount
70+
});
71+
}
72+
73+
/// @notice Converts an Ethereum address to FVM address format
74+
/// @param _addr The Ethereum address to convert
75+
/// @return FVM formatted address
76+
function convertToFvmAddr(address _addr) internal pure returns (FvmAddress memory) {
77+
return FvmAddress({
78+
addrType: 1, // f1 address type
79+
payload: abi.encodePacked(_addr)
80+
});
81+
}
82+
}

0 commit comments

Comments
 (0)