Skip to content

Commit

Permalink
chore: cross chain struct implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
zhoujia6139 committed Dec 11, 2023
1 parent e9c926f commit 9f8ed4c
Show file tree
Hide file tree
Showing 36 changed files with 388 additions and 216 deletions.
31 changes: 31 additions & 0 deletions contracts/cross-chain/BridgeDefine.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

enum MessageType {
AddNewCrossChainERC721,
BridgeERC721,
ERC721DELEGATION
}

struct BridgeMessage {
MessageType msgType;
bytes data;
}

struct BridgeERC721Message {
address asset;
uint256[] tokenIds;
address receiver;
}

struct ERC721DelegationMessage {
address asset;
address delegateTo;
uint256[] tokenIds;
bool value;
}

//library BridgeDefine {
//
//
//}
12 changes: 12 additions & 0 deletions contracts/cross-chain/L1/IParaxBridgeNFTVault.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {BridgeERC721Message, ERC721DelegationMessage} from "../BridgeDefine.sol";

interface IParaxBridgeNFTVault {
function releaseNFT(BridgeERC721Message calldata message) external;

function updateTokenDelegation(
ERC721DelegationMessage calldata delegationInfo
) external;
}
10 changes: 10 additions & 0 deletions contracts/cross-chain/L1/IParaxL1MessageHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {MessageType, BridgeMessage, BridgeERC721Message} from "../BridgeDefine.sol";

interface IParaxL1MessageHandler {
function addBridgeAsset(address asset) external;

function bridgeAsset(BridgeERC721Message calldata message) external;
}
86 changes: 86 additions & 0 deletions contracts/cross-chain/L1/ParaxBridgeNFTVault.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {BridgeERC721Message, ERC721DelegationMessage} from "../BridgeDefine.sol";
import {IERC721} from "../../dependencies/openzeppelin/contracts/IERC721.sol";
import {Errors} from "../../protocol/libraries/helpers/Errors.sol";
import "../../dependencies/openzeppelin/upgradeability/Initializable.sol";
import "../../dependencies/openzeppelin/upgradeability/OwnableUpgradeable.sol";
import "./IParaxL1MessageHandler.sol";
import {IDelegateRegistry} from "../../dependencies/delegation/IDelegateRegistry.sol";

contract ParaxBridgeNFTVault is Initializable, OwnableUpgradeable {
IParaxL1MessageHandler internal immutable l1MsgHander;

IDelegateRegistry delegationRegistry;

mapping(address => bool) supportAsset;

constructor(IParaxL1MessageHandler msgHandler) {
l1MsgHander = msgHandler;
}

modifier onlyMsgHandler() {
require(msg.sender == address(l1MsgHander), Errors.ONLY_MSG_HANDLER);
_;
}

function addBridgeAsset(address asset) external {
require(supportAsset[asset] == false, "asset already added");
supportAsset[asset] = true;
l1MsgHander.addBridgeAsset(asset);
}

function bridgeAsset(
address asset,
uint256[] calldata tokenIds,
address receiver
) external {
require(supportAsset[asset] == true, "asset already added");
//lock asset
uint256 length = tokenIds.length;
for (uint256 index = 0; index < length; index++) {
uint256 tokenId = tokenIds[index];
IERC721(asset).safeTransferFrom(msg.sender, address(this), tokenId);
}

//send cross chain msg
l1MsgHander.bridgeAsset(
BridgeERC721Message({
asset: asset,
tokenIds: tokenIds,
receiver: receiver
})
);
}

function releaseNFT(
BridgeERC721Message calldata message
) external onlyMsgHandler {
uint256 length = message.tokenIds.length;
for (uint256 index = 0; index < length; index++) {
uint256 tokenId = message.tokenIds[index];
IERC721(message.asset).safeTransferFrom(
address(this),
message.receiver,
tokenId
);
}
}

function updateTokenDelegation(
ERC721DelegationMessage calldata delegationInfo
) external onlyMsgHandler {
uint256 length = delegationInfo.tokenIds.length;
for (uint256 index = 0; index < length; index++) {
uint256 tokenId = delegationInfo.tokenIds[index];
delegationRegistry.delegateERC721(
delegationInfo.delegateTo,
delegationInfo.asset,
tokenId,
"",
delegationInfo.value
);
}
}
}
49 changes: 49 additions & 0 deletions contracts/cross-chain/L1/ParaxL1MessageHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;

import {MessageType, BridgeMessage, BridgeERC721Message} from "../BridgeDefine.sol";
import {Errors} from "../../protocol/libraries/helpers/Errors.sol";
import "./IParaxBridgeNFTVault.sol";

contract ParaxL1MessageHandler {
IParaxBridgeNFTVault internal immutable nftVault;
address immutable bridgeImpl;

constructor(IParaxBridgeNFTVault vault, address bridge) {
nftVault = vault;
bridgeImpl = bridge;
}

modifier onlyVault() {
require(msg.sender == address(nftVault), Errors.ONLY_VAULT);
_;
}

modifier onlyBridge() {
require(msg.sender == address(bridgeImpl), Errors.ONLY_BRIDGE);
_;
}

function addBridgeAsset(address asset) external onlyVault {}

function bridgeAsset(
BridgeERC721Message calldata message
) external onlyVault {}

function bridgeReceive(BridgeMessage calldata message) external onlyBridge {
if (message.msgType == MessageType.BridgeERC721) {
BridgeERC721Message memory message = abi.decode(
message.data,
(BridgeERC721Message)
);
nftVault.releaseNFT(message);
} else if (message.msgType == MessageType.ERC721DELEGATION) {
ERC721DelegationMessage memory message = abi.decode(
message.data,
(ERC721DelegationMessage)
);
nftVault.updateTokenDelegation(message);
}
}
}
47 changes: 47 additions & 0 deletions contracts/cross-chain/L2/BridgeERC721.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {ERC721} from "../../dependencies/openzeppelin/contracts/ERC721.sol";
import {ERC721Enumerable} from "../../dependencies/openzeppelin/contracts/ERC721Enumerable.sol";
import {Errors} from "../../protocol/libraries/helpers/Errors.sol";

contract BridgeERC21 is ERC721Enumerable {
address internal immutable handler;

modifier onlyHandler() {
require(msg.sender == handler, Errors.ONLY_VAULT);
_;
}

constructor(
string memory name,
string memory symbol,
address _handler
) ERC721(name, symbol) {
handler = _handler;
}

function mint(
address to,
uint256[] calldata tokenIds
) external onlyHandler {
uint256 length = tokenIds.length;
for (uint256 index = 0; index < length; index++) {
uint256 tokenId = tokenIds[index];
_mint(to, tokenId);
}
}

function burn(
address from,
uint256[] calldata tokenIds
) external onlyHandler {
uint256 length = tokenIds.length;
for (uint256 index = 0; index < length; index++) {
uint256 tokenId = tokenIds[index];
address owner = ownerOf(tokenId);
require(owner == from, "invalid");
_burn(tokenId);
}
}
}
34 changes: 34 additions & 0 deletions contracts/cross-chain/L2/BridgeERC721Handler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {MessageType, BridgeMessage, BridgeERC721Message} from "../BridgeDefine.sol";
import {ERC721} from "../../dependencies/openzeppelin/contracts/ERC721.sol";
import "./IParaxL2MessageHandler.sol";
import "./IBridgeERC721.sol";
import {Errors} from "../../protocol/libraries/helpers/Errors.sol";

contract BridgeERC21Handler {
IParaxL2MessageHandler internal immutable l2MsgHandler;

//origin asset -> bridge asset
mapping(address => address) getBridgeAsset;
mapping(address => address) getOriginAsset;

constructor(IParaxL2MessageHandler msgHandler) {
l2MsgHandler = msgHandler;
}

modifier onlyMsgHandler() {
require(msg.sender == address(l2MsgHandler), Errors.ONLY_HANDLER);
_;
}

function bridgeAsset(
BridgeERC721Message calldata message
) external onlyMsgHandler {
address bridgeAsset = getBridgeAsset[message.asset];
require(bridgeAsset != address(0), "invalid");

IBridgeERC721(bridgeAsset).mint(message.receiver, message.tokenIds);
}
}
8 changes: 8 additions & 0 deletions contracts/cross-chain/L2/IBridgeERC721.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IBridgeERC721 {
function mint(address to, uint256[] calldata tokenId) external;

function burn(address from, uint256[] calldata tokenId) external;
}
12 changes: 12 additions & 0 deletions contracts/cross-chain/L2/IParaxL2MessageHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {MessageType, BridgeMessage, BridgeERC721Message, ERC721DelegationMessage} from "../BridgeDefine.sol";

interface IParaxL2MessageHandler {
//function bridgeAsset(BridgeERC721Message calldata message) external;

function updateTokenDelegation(
ERC721DelegationMessage calldata delegationInfo
) external;
}
38 changes: 38 additions & 0 deletions contracts/cross-chain/L2/ParaxL2MessageHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {MessageType, BridgeMessage} from "../BridgeDefine.sol";
import "./BridgeERC721Handler.sol";
import "./IParaxL2MessageHandler.sol";

contract ParaxL2MessageHandler is IParaxL2MessageHandler {
BridgeERC21Handler internal immutable erc712Handler;
address immutable bridgeImpl;
address immutable paraX;

constructor(BridgeERC21Handler handler) {
erc712Handler = handler;
}

function bridgeReceive(BridgeMessage calldata message) external {
require(msg.sender == bridgeImpl, "");
if (message.msgType == MessageType.BridgeERC721) {
BridgeERC721Message memory message = abi.decode(
message.data,
(BridgeERC721Message)
);
erc712Handler.bridgeAsset(message);
} else {}
}

function updateTokenDelegation(
ERC721DelegationMessage calldata delegationInfo
) external {
require(msg.sender == paraX, Errors.ONLY_PARAX);

BridgeMessage memory message;
message.msgType = MessageType.ERC721DELEGATION;
message.data = abi.encode(delegationInfo);
//send msg
}
}
4 changes: 3 additions & 1 deletion contracts/interfaces/IPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {IPoolPositionMover} from "./IPoolPositionMover.sol";
import {IPoolAAPositionMover} from "./IPoolAAPositionMover.sol";
import "./IPoolApeStaking.sol";
import "./IPoolBorrowAndStake.sol";
import "./IPoolCrossChain.sol";

/**
* @title IPool
Expand All @@ -23,7 +24,8 @@ interface IPool is
IParaProxyInterfaces,
IPoolPositionMover,
IPoolBorrowAndStake,
IPoolAAPositionMover
IPoolAAPositionMover,
IPoolCrossChain
{

}
20 changes: 20 additions & 0 deletions contracts/interfaces/IPoolCrossChain.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;

import {DataTypes} from "../protocol/libraries/types/DataTypes.sol";

/**
* @title IPool
*
* @notice Defines the basic interface for an ParaSpace Pool.
**/
interface IPoolCrossChain {
function updateTokenDelegation(
address delegateTo,
address underlyingAsset,
uint256[] calldata tokenIds,
bool value
) external;

function CROSS_CHAIN_MSG_HANDLER() external view returns (address);
}
6 changes: 0 additions & 6 deletions contracts/interfaces/ITokenDelegation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,4 @@ interface ITokenDelegation {
uint256[] calldata tokenIds,
bool value
) external;

/**
* @notice Returns the address of the delegation registry of this nToken
* @return The address of the delegation registry
**/
function DELEGATE_REGISTRY() external view returns (address);
}
2 changes: 1 addition & 1 deletion contracts/mocks/upgradeability/MockNToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {IPool} from "../../interfaces/IPool.sol";
import {IRewardController} from "../../interfaces/IRewardController.sol";

contract MockNToken is NToken {
constructor(IPool pool, address delegateRegistry) NToken(pool, false, delegateRegistry) {}
constructor(IPool pool) NToken(pool, false) {}

function getRevision() internal pure override returns (uint256) {
return 999;
Expand Down
Loading

0 comments on commit 9f8ed4c

Please sign in to comment.