From 73eb4ccde78876f7bd687d495c5318f2bb8a3880 Mon Sep 17 00:00:00 2001 From: CJ42 Date: Tue, 24 Sep 2024 08:57:37 +0800 Subject: [PATCH] refactor: override functions to extract params from LSP7 calldata --- README.md | 7 ++++++- src/HypLSP7.sol | 24 ++++++++++++++++++++++++ src/TokenMessageForLSP7.sol | 25 +++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/TokenMessageForLSP7.sol diff --git a/README.md b/README.md index cc5e2fe..5545342 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,11 @@ ## Architecture & Workflow +The flow for bridging tokens is generally as follow: + +- if the token is originally from ETH, the token is locked on ETHEREUM, and minted on LUKSO. +- if the token is originally from LUKSO, the token is burnt on LUKSO, minted on ETHEREUM. + ### Ethereum -> LUKSO ![Ethereum to LUKSO bridge flow](./assets/flow-ethereum-lukso-hashi-bridge.png) @@ -79,8 +84,8 @@ ### Relevant links & resources -- [Architecture diagrams](https://hackmd.io/WXwzLS5TS4q_G3C7w2DkiA) - [Cross Chain Alliance - Hashi](https://crosschain-alliance.gitbook.io/hashi) +- [Hyperlane smart contracts monorepo](https://github.com/hyperlane-xyz/hyperlane-monorepo) ## Getting Started diff --git a/src/HypLSP7.sol b/src/HypLSP7.sol index b5bbca0..cd4cd60 100644 --- a/src/HypLSP7.sol +++ b/src/HypLSP7.sol @@ -6,6 +6,9 @@ import { LSP7DigitalAssetInitAbstract } from "@lukso/lsp7-contracts/contracts/LS import { TokenRouter } from "@hyperlane-xyz/core/contracts/token/libs/TokenRouter.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +// libraries +import { TokenMessageForLSP7 } from "./TokenMessageForLSP7.sol"; + /** * @title LSP7 version of the Hyperlane ERC20 Token Router * @dev https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/HypERC20.sol @@ -90,4 +93,25 @@ contract HypLSP7 is LSP7DigitalAssetInitAbstract, TokenRouter { { LSP7DigitalAssetInitAbstract._mint(_recipient, _amount, true, ""); } + + function _transferRemote( + uint32 _destination, + bytes32 _recipient, + uint256 _amountOrId, + uint256 _value, + bytes memory _hookMetadata, + address _hook + ) + internal + virtual + override(TokenRouter) + returns (bytes32 messageId) + { + bytes memory _tokenMetadata = _transferFromSender(_amountOrId); + bytes memory _tokenMessage = TokenMessageForLSP7.format(_recipient, _amountOrId, _tokenMetadata); + + messageId = _Router_dispatch(_destination, _value, _tokenMessage, _hookMetadata, _hook); + + emit SentTransferRemote(_destination, _recipient, _amountOrId); + } } diff --git a/src/TokenMessageForLSP7.sol b/src/TokenMessageForLSP7.sol new file mode 100644 index 0000000..5da1ebb --- /dev/null +++ b/src/TokenMessageForLSP7.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.8.0; + +/// @dev Adjusted version of the TokenMessage library from Hyperlane +/// to extract parameters from the calldata of an LSP7 transfer +/// according to the `transfer(address,address,uint256,bool,bytes)` signature. +library TokenMessageForLSP7 { + function format(bytes32 _recipient, uint256 _amount, bytes memory _metadata) internal view returns (bytes memory) { + return abi.encodePacked( + msg.sender, // TODO: which sender should be specified here? Should we add an extra parameter? + _recipient, + _amount, + true, // force param set to `true` by default + _metadata + ); + } + + function recipient(bytes calldata message) internal pure returns (bytes32) { + return bytes32(message[32:64]); + } + + function amount(bytes calldata message) internal pure returns (uint256) { + return uint256(bytes32(message[64:96])); + } +}