Module 4 - About Bridge Adapters
Adapters for Bridging Assets
This Module is Useful for Understanding the AssetBridgeAdapter and NitroAdapter Smart Contracts which are helpful for learning about Bridging Adapters. Refer this Repository for Smart Contracts.
Asset Bridge Adapter
This Tutorial will Guide you through the functionality of the AssetBridgeAdapter.sol
Smart Contract. This Contract is Designed to Bridge Funds and Instructions to another Blockchain. It Utilizes the RouterIntentEoaAdapterWithoutDataProvider
for Executing Transactions and Interacting with an AssetBridge for Transferring or Swapping Tokens.
-
Contract Structure - The
AssetBridgeAdapter
Contract inherits fromRouterIntentEoaAdapterWithoutDataProvider
and Integrates with anAssetBridge
for Asset Bridging Operations. It usesSafeERC20
for Secure Token Operations and follows a Structure that Separates Data Storage (AssetBridgeDataStore
) from the Main Adapter Logic. The Contract imports Several Dependencies -a)
RouterIntentEoaAdapterWithoutDataProvider
andEoaExecutorWithoutDataProvider
from@routerprotocol/intents-core
.b)
Errors
for error handling.c)
IERC20
andSafeERC20
from a utilities library.d)
IAssetBridge
interface.e)
Ownable
fromOpenZeppelin
for access control. -
Data Storage Contract - The
AssetBridgeDataStore
Contract Stores the Address of theAssetBridge
and allows the Owner to Update it.contract AssetBridgeDataStore is Ownable {address public assetBridge;constructor(address _owner, address _assetBridge) {_transferOwnership(_owner);assetBridge = _assetBridge;}function setAssetBridge(address _assetBridge) external onlyOwner {assetBridge = _assetBridge;}} -
Main Adapter Contract - The
AssetBridgeAdapter
Contract Defines -a)
assetBridgeDataStore
to StoreAssetBridge
Address.b)
PARTNER_ID
as a Constant Identifier.c) A Constructor to Initialize the Contract and Deploy
AssetBridgeDataStore
.d)
name()
function to return the Adapter’s Name.e)
execute()
function to hHndle the Execution Logic for Bridging Tokens.contract AssetBridgeAdapter is RouterIntentEoaAdapterWithoutDataProvider {using SafeERC20 for IERC20;AssetBridgeDataStore public immutable assetBridgeDataStore;uint256 public constant PARTNER_ID = 1;constructor(address __native,address __wnative,address __assetBridge)RouterIntentEoaAdapterWithoutDataProvider(__native, __wnative){assetBridgeDataStore = new AssetBridgeDataStore(msg.sender,__assetBridge);}function name() public pure override returns (string memory) {return "AssetBridgeAdapter";}function execute(bytes calldata data) external payable override returns (address[] memory tokens) {// implementation details}} -
Deployment - To Deploy the
AssetBridgeAdapter
, you need to Provide the Addresses for Native and Wrapped Native Tokens, as well as theAssetBridge
Contract.address __native = 0x...; // Native token addressaddress __wnative = 0x...; // Wrapped native token addressaddress __assetBridge = 0x...; // AssetBridge contract addressAssetBridgeAdapter adapter = new AssetBridgeAdapter(__native, __wnative, __assetBridge); -
Functions -
a) name() - This function returns the name of the Adapter.
```solfunction name() public pure override returns (string memory) {return "AssetBridgeAdapter";}```b) execute() - The
execute
function Performs the following Actions Based on thetxType
Decoded from the Input Data -```solfunction execute(bytes calldata data) external payable override returns (address[] memory tokens) {// Implementation details}```- Transfer Token
- Directly transfers tokens using
IAssetBridge.transferToken
.
- Swap and Transfer Token
- Swaps and then transfers tokens using
IAssetBridge.swapAndTransferToken
.
-
Usage Example - To Use the
AssetBridgeAdapter
, you need to Call the Execute function with appropriate calldata.-
Example: Transfer Token
bytes memory data = abi.encode(uint8(0), // txType for transferIAssetBridge.TransferPayload({ /* payload details */ }),uint64(21000), // Destination gas limitbytes("") // Optional instruction);adapter.execute{value: amount}(data); -
Example: Swap and Transfer Token
bytes memory data = abi.encode(uint8(1), // txType for swap and transferIAssetBridge.SwapTransferPayload({ /* payload details */ }),uint64(21000), // Destination gas limitbytes("") // Optional instruction);adapter.execute{value: amount}(data);
-
Conclusion
The AssetBridgeAdapter
Contract Provides a Robust Solution for Bridging Assets and Instructions across Chains. By following this Tutorial, Developers can understand the Contract’s Structure, deploy it, and use its functions effectively.
NitroAdapter
This Tutorial will Guide you through the functionality and Usage of the NitroAdapter
Smart Contract. The NitroAdapter
Contract is Designed to facilitate the Bridging of Assets and Instructions to another Blockchain. It Integrates with Both an AssetForwarder
and DexSpan
to Perform Token Deposits and Swaps.
-
Contract Structure - The
NitroAdapter
Contract inherits fromRouterIntentEoaAdapterWithoutDataProvider
and Interacts withAssetForwarder
andDexSpan
for Asset Bridging Operations. It usesSafeERC20
for Secure Token Operations and follows a Structure that Separates Data Storage (NitroDataStore
) from the Main Adapter Logic. The Contract imports Several Dependencies -a)
RouterIntentEoaAdapterWithoutDataProvider
andEoaExecutorWithoutDataProvider
from@routerprotocol/intents-core
.b)
Errors
for error handling.c)
IERC20
andSafeERC20
from a utilities library.d)
IAssetForwarder
andIDexSpan
interfaces.e)
Ownable
fromOpenZeppelin
for access control. -
Data Storage Contract - The
NitroDataStore
Contract Stores the Addresses of theAssetForwarder
andDexSpan
and allows the Owner to Update them.contract NitroDataStore is Ownable {address public assetForwarder;address public dexspan;constructor(address _owner, address _assetForwarder, address _dexspan) {_transferOwnership(_owner);assetForwarder = _assetForwarder;dexspan = _dexspan;}function setDexSpan(address _dexspan) external onlyOwner {dexspan = _dexspan;}function setAssetForwarder(address _assetForwarder) external onlyOwner {assetForwarder = _assetForwarder;}} -
Main Adapter Contract - The
NitroAdapter
Contract Defines -a)
USDC
as the address of the USDC Token.b)
NitroDataStore
to storeAssetForwarder
andDexSpan
addresses.c)
PARTNER_ID
as a constant identifier.c) A constructor to initialize the Contract and deploy
NitroDataStore
.d)
name()
function to return the Adapter’s name.e)
execute()
function to handle the Execution Logic for Bridging Tokens.contract NitroAdapter is RouterIntentEoaAdapterWithoutDataProvider {using SafeERC20 for IERC20;address public immutable usdc;NitroDataStore public immutable nitroDataStore;uint256 public constant PARTNER_ID = 1;struct SwapAndDepositData {uint256 partnerId;bytes32 destChainIdBytes;bytes recipient;address refundRecipient;uint256 feeAmount;IDexSpan.SwapParams swapData;bytes message;}struct UsdcCCTPData {uint256 partnerId;uint256 amount;bytes32 destChainIdBytes;bytes32 recipient;}constructor(address __native,address __wnative,address __assetForwarder,address __dexspan)RouterIntentEoaAdapterWithoutDataProvider(__native, __wnative){nitroDataStore = new NitroDataStore(msg.sender,__assetForwarder,__dexspan);usdc = IAssetForwarder(__assetForwarder).usdc();}function name() public pure override returns (string memory) {return "NitroAdapter";}function execute(bytes calldata data) external payable override returns (address[] memory tokens) {// Implementation details}} -
Deployment - To Deploy the
NitroAdapter
, you need to Provide the addresses for Native and Wrapped Native Tokens, as well as theAssetForwarder
andDexSpan
Contracts.address __native = 0x...; // Native token addressaddress __wnative = 0x...; // Wrapped native token addressaddress __assetForwarder = 0x...; // AssetForwarder contract addressaddress __dexspan = 0x...; // DexSpan contract addressNitroAdapter adapter = new NitroAdapter(__native, __wnative, __assetForwarder, __dexspan); -
Functions -
a) name() - This function returns the name of the Adapter.
```solfunction name() public pure override returns (string memory) {return "NitroAdapter";}```b) execute() - The
execute
function Performs the following Actions Based on thetxType
Decoded from the Input Data -```solfunction execute(bytes calldata data) external payable override returns (address[] memory tokens) {// Implementation details}```- iDeposit
- Directly Deposits Tokens using
IAssetForwarder.iDeposit
.
- Directly Deposits Tokens using
- Swap and Deposit
- Swaps and then Deposits Tokens using
IDexSpan.swapAndDeposit
.
- Swaps and then Deposits Tokens using
- USDC Request
- Requests USDC Deposit using
IAssetForwarder.iDepositUSDC
.
- Requests USDC Deposit using
- Swap and Deposit USDC
- Swaps and then Deposits USDC Tokens using
IDexSpan.swapAndDeposit
.
- Swaps and then Deposits USDC Tokens using
- iDeposit
-
Usage Example - To use the
NitroAdapter
, you need to Call the execute function with appropriate calldata.-
Example: iDeposit
bytes memory data = abi.encode(uint8(0), // txType for iDepositIAssetForwarder.DepositData({ /* payload details */ }),bytes("destinationToken"), // Destination tokenbytes("recipientAddress"), // Recipient addressbytes("") // Optional message);adapter.execute{value: amount}(data); -
Example: Swap and Deposit
bytes memory data = abi.encode(uint8(1), // txType for swap and depositSwapAndDepositData({ /* payload details */ }),bytes("") // Optional message);adapter.execute{value: amount}(data); -
Example: USDC Request
bytes memory data = abi.encode(uint8(2), // txType for USDC requestUsdcCCTPData({ /* payload details */ }));adapter.execute(data); -
Example: Swap and Deposit USDC
bytes memory data = abi.encode(uint8(3), // txType for swap and deposit USDCSwapAndDepositData({ /* payload details */ }));adapter.execute{value: amount}(data);
-
Conclusion
The NitroAdapter
Contract provides a Robust Solution for Bridging Assets and Instructions across Chains. By following this Tutorial, Developers can Understand the Contract’s Structure, Deploy it, and use its functions Effectively.