From 11a94c1e830033f593491f9b74dd294bff718552 Mon Sep 17 00:00:00 2001 From: zhoujia6139 Date: Mon, 25 Dec 2023 18:15:23 +0800 Subject: [PATCH] chore: update apestaking doc and delegation implementation --- contracts/cross-chain/BridgeDefine.sol | 13 -- .../cross-chain/L1/IParaxBridgeNFTVault.sol | 12 - .../cross-chain/L1/IParaxL1MessageHandler.sol | 6 +- contracts/cross-chain/L1/IVaultApeStaking.sol | 56 ++++- contracts/cross-chain/L1/IVaultParaX.sol | 11 + .../cross-chain/L1/ParaxBridgeNFTVault.sol | 90 ------- .../cross-chain/L1/ParaxL1MessageHandler.sol | 42 ++-- contracts/cross-chain/L1/VaultApeStaking.sol | 16 +- contracts/cross-chain/L1/VaultParaX.sol | 50 ++++ contracts/cross-chain/L2/BridgeERC721.sol | 47 ---- .../cross-chain/L2/BridgeERC721Handler.sol | 34 --- contracts/cross-chain/L2/IBridgeERC721.sol | 8 - .../cross-chain/L2/IParaxL2MessageHandler.sol | 9 +- .../cross-chain/L2/ParaxL2MessageHandler.sol | 45 ++-- .../cross-chain/socket/IExecutionManager.sol | 191 +++++++++++++++ contracts/cross-chain/socket/ISocket.sol | 219 ++++++++++++++++++ .../cross-chain/socket/ITransmitManager.sol | 43 ++++ contracts/protocol/pool/PoolCrossChain.sol | 63 +++++ contracts/protocol/pool/PoolParameters.sol | 1 - .../base/MintableIncentivizedERC721.sol | 4 - 20 files changed, 685 insertions(+), 275 deletions(-) delete mode 100644 contracts/cross-chain/L1/IParaxBridgeNFTVault.sol create mode 100644 contracts/cross-chain/L1/IVaultParaX.sol delete mode 100644 contracts/cross-chain/L1/ParaxBridgeNFTVault.sol create mode 100644 contracts/cross-chain/L1/VaultParaX.sol delete mode 100644 contracts/cross-chain/L2/BridgeERC721.sol delete mode 100644 contracts/cross-chain/L2/BridgeERC721Handler.sol delete mode 100644 contracts/cross-chain/L2/IBridgeERC721.sol create mode 100644 contracts/cross-chain/socket/IExecutionManager.sol create mode 100644 contracts/cross-chain/socket/ISocket.sol create mode 100644 contracts/cross-chain/socket/ITransmitManager.sol create mode 100644 contracts/protocol/pool/PoolCrossChain.sol diff --git a/contracts/cross-chain/BridgeDefine.sol b/contracts/cross-chain/BridgeDefine.sol index cdf4ff6b..d0567de9 100644 --- a/contracts/cross-chain/BridgeDefine.sol +++ b/contracts/cross-chain/BridgeDefine.sol @@ -2,8 +2,6 @@ pragma solidity ^0.8.0; enum MessageType { - AddNewCrossChainERC721, - BridgeERC721, ERC721DELEGATION } @@ -12,20 +10,9 @@ struct BridgeMessage { bytes data; } -struct BridgeERC721Message { - address asset; - uint256[] tokenIds; - address receiver; -} - struct ERC721DelegationMessage { address asset; address delegateTo; uint256[] tokenIds; bool value; } - -//library BridgeDefine { -// -// -//} diff --git a/contracts/cross-chain/L1/IParaxBridgeNFTVault.sol b/contracts/cross-chain/L1/IParaxBridgeNFTVault.sol deleted file mode 100644 index e1bde7b2..00000000 --- a/contracts/cross-chain/L1/IParaxBridgeNFTVault.sol +++ /dev/null @@ -1,12 +0,0 @@ -// 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; -} diff --git a/contracts/cross-chain/L1/IParaxL1MessageHandler.sol b/contracts/cross-chain/L1/IParaxL1MessageHandler.sol index a1d2d70c..d25d3edf 100644 --- a/contracts/cross-chain/L1/IParaxL1MessageHandler.sol +++ b/contracts/cross-chain/L1/IParaxL1MessageHandler.sol @@ -1,10 +1,6 @@ // 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; + function migration(address asset) external; } diff --git a/contracts/cross-chain/L1/IVaultApeStaking.sol b/contracts/cross-chain/L1/IVaultApeStaking.sol index cb7e3c7c..8e2c137e 100644 --- a/contracts/cross-chain/L1/IVaultApeStaking.sol +++ b/contracts/cross-chain/L1/IVaultApeStaking.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {BridgeERC721Message, ERC721DelegationMessage} from "../BridgeDefine.sol"; - interface IVaultApeStaking { struct TokenStatus { //record tokenId reward debt position @@ -152,38 +150,88 @@ interface IVaultApeStaking { */ function compoundBAKC(BAKCPairActionInfo calldata actionInfo) external; + /** + * @notice enter ape staking pool when bayc/mayc/bakc transferred to vault contract. + * It's an interceptor call, can only be called by vault self. + * @param nft Identify pool + * @param tokenId The tokenId of the nft + * @param beneficiary The reward beneficiary for the pool position + */ function onboardCheckApeStakingPosition( address nft, uint32 tokenId, address beneficiary ) external; + /** + * @notice exit ape staking pool when bayc/mayc/bakc transferred out from vault contract. + * It's an interceptor call, can only be called by vault self. + * @param nft Identify pool + * @param tokenId The tokenId of the nft + */ function offboardCheckApeStakingPosition( address nft, uint32 tokenId ) external; + /** + * @notice unstake the ape coin position on the ape. can only be called by the bot. + * @param isBAYC if Ape is BAYC + * @param tokenIds Ape token ids + */ function unstakeApe(bool isBAYC, uint32[] calldata tokenIds) external; + /** + * @notice set ape coin staking bot address. can only be called by pool admin. + */ function setApeStakingBot(address _apeStakingBot) external; + /** + * @notice set compound fee rate. can only be called by pool admin. + */ function setCompoundFeeRate(uint32 _compoundFeeRate) external; + /** + * @notice set cApe income rate. can only be called by pool admin. + * @param nft Identify pool + * @param rate new cApe income rate + */ + function setCApeIncomeRate(address nft, uint32 rate) external; + + /** + * @notice claim compound fee. can only be called by bot. + */ function claimCompoundFee(address receiver) external; + /** + * @notice update the position reward beneficiary. can only be called by bridge. + *Nft owner can launch the cross-chain calling from L2 + * @param nft Identify pool + * @param tokenIds The tokenIds of the nft + */ function updateBeneficiary( address nft, uint32[] calldata tokenIds, address newBenificiary ) external; + /** + * @notice Pauses the contract. Only pool admin or emergency admin can call this function + **/ function pause() external; + /** + * @notice Unpause the contract. Only pool admin can call this function + **/ function unpause() external; + /** + * @notice initialization operation for the vault + **/ function initialize() external; + /** + * @notice fetch accumulated compound fee. + **/ function compoundFee() external view returns (uint256); - - function setCApeIncomeRate(address nft, uint32 rate) external; } diff --git a/contracts/cross-chain/L1/IVaultParaX.sol b/contracts/cross-chain/L1/IVaultParaX.sol new file mode 100644 index 00000000..34028e6a --- /dev/null +++ b/contracts/cross-chain/L1/IVaultParaX.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IVaultParaX { + function updateTokenDelegation( + address delegateTo, + address asset, + uint256[] calldata tokenIds, + bool value + ) external; +} diff --git a/contracts/cross-chain/L1/ParaxBridgeNFTVault.sol b/contracts/cross-chain/L1/ParaxBridgeNFTVault.sol deleted file mode 100644 index e5828477..00000000 --- a/contracts/cross-chain/L1/ParaxBridgeNFTVault.sol +++ /dev/null @@ -1,90 +0,0 @@ -// 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 internal immutable delegationRegistry; - - mapping(address => bool) supportAsset; - - constructor( - IParaxL1MessageHandler msgHandler, - address _delegationRegistry - ) { - l1MsgHander = msgHandler; - delegationRegistry = IDelegateRegistry(_delegationRegistry); - } - - 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 - ); - } - } -} diff --git a/contracts/cross-chain/L1/ParaxL1MessageHandler.sol b/contracts/cross-chain/L1/ParaxL1MessageHandler.sol index f7b62213..e9805eb1 100644 --- a/contracts/cross-chain/L1/ParaxL1MessageHandler.sol +++ b/contracts/cross-chain/L1/ParaxL1MessageHandler.sol @@ -2,48 +2,38 @@ pragma solidity ^0.8.0; pragma abicoder v2; -import {MessageType, BridgeMessage, BridgeERC721Message} from "../BridgeDefine.sol"; +import {MessageType, BridgeMessage, ERC721DelegationMessage} from "../BridgeDefine.sol"; import {Errors} from "../../protocol/libraries/helpers/Errors.sol"; -import "./IParaxBridgeNFTVault.sol"; +import "./IVaultParaX.sol"; contract ParaxL1MessageHandler { - IParaxBridgeNFTVault internal immutable nftVault; - address immutable bridgeImpl; + address internal immutable vault; + address public immutable socket; - constructor(IParaxBridgeNFTVault vault, address bridge) { - nftVault = vault; - bridgeImpl = bridge; - } - - modifier onlyVault() { - require(msg.sender == address(nftVault), Errors.ONLY_VAULT); - _; + constructor(address vault_, address bridge) { + vault = vault_; + socket = bridge; } modifier onlyBridge() { - require(msg.sender == address(bridgeImpl), Errors.ONLY_BRIDGE); + require(msg.sender == socket, Errors.ONLY_BRIDGE); _; } - function addBridgeAsset(address asset) external onlyVault {} - - function bridgeAsset( - BridgeERC721Message calldata message - ) external onlyVault {} + function migration(address asset) external {} function bridgeReceive(BridgeMessage calldata message) external onlyBridge { - if (message.msgType == MessageType.BridgeERC721) { - BridgeERC721Message memory erc721Message = abi.decode( - message.data, - (BridgeERC721Message) - ); - nftVault.releaseNFT(erc721Message); - } else if (message.msgType == MessageType.ERC721DELEGATION) { + if (message.msgType == MessageType.ERC721DELEGATION) { ERC721DelegationMessage memory delegationMsg = abi.decode( message.data, (ERC721DelegationMessage) ); - nftVault.updateTokenDelegation(delegationMsg); + IVaultParaX(vault).updateTokenDelegation( + delegationMsg.delegateTo, + delegationMsg.asset, + delegationMsg.tokenIds, + delegationMsg.value + ); } } } diff --git a/contracts/cross-chain/L1/VaultApeStaking.sol b/contracts/cross-chain/L1/VaultApeStaking.sol index 39d79828..7492f173 100644 --- a/contracts/cross-chain/L1/VaultApeStaking.sol +++ b/contracts/cross-chain/L1/VaultApeStaking.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {BridgeERC721Message, ERC721DelegationMessage} from "../BridgeDefine.sol"; import "../../dependencies/openzeppelin/contracts/ReentrancyGuard.sol"; import "../../dependencies/openzeppelin/contracts//Pausable.sol"; import "../../dependencies/openzeppelin/contracts/SafeCast.sol"; @@ -387,6 +386,7 @@ contract VaultApeStaking is ReentrancyGuard, Pausable, IVaultApeStaking { } } + /// @inheritdoc IVaultApeStaking function offboardCheckApeStakingPosition( address nft, uint32 tokenId @@ -664,6 +664,7 @@ contract VaultApeStaking is ReentrancyGuard, Pausable, IVaultApeStaking { ); } + /// @inheritdoc IVaultApeStaking function setApeStakingBot(address _apeStakingBot) external onlyPoolAdmin { ApeStakingStorage storage ds = apeStakingStorage(); address oldValue = ds.apeStakingBot; @@ -673,6 +674,7 @@ contract VaultApeStaking is ReentrancyGuard, Pausable, IVaultApeStaking { } } + /// @inheritdoc IVaultApeStaking function setCompoundFeeRate( uint32 _compoundFeeRate ) external onlyPoolAdmin { @@ -686,6 +688,7 @@ contract VaultApeStaking is ReentrancyGuard, Pausable, IVaultApeStaking { } } + /// @inheritdoc IVaultApeStaking function setCApeIncomeRate( address nft, uint32 rate @@ -700,6 +703,7 @@ contract VaultApeStaking is ReentrancyGuard, Pausable, IVaultApeStaking { } } + /// @inheritdoc IVaultApeStaking function claimCompoundFee(address receiver) external { ApeStakingStorage storage ds = apeStakingStorage(); require(ds.apeStakingBot == msg.sender, Errors.NOT_APE_STAKING_BOT); @@ -713,11 +717,13 @@ contract VaultApeStaking is ReentrancyGuard, Pausable, IVaultApeStaking { } } + /// @inheritdoc IVaultApeStaking function compoundFee() external view returns (uint256) { ApeStakingStorage storage ds = apeStakingStorage(); return ds.accuCompoundFee; } + /// @inheritdoc IVaultApeStaking function updateBeneficiary( address nft, uint32[] calldata tokenIds, @@ -753,16 +759,12 @@ contract VaultApeStaking is ReentrancyGuard, Pausable, IVaultApeStaking { } } - /** - * @notice Pauses the contract. Only pool admin or emergency admin can call this function - **/ + /// @inheritdoc IVaultApeStaking function pause() external onlyEmergencyOrPoolAdmin { _pause(); } - /** - * @notice Unpause the contract. Only pool admin can call this function - **/ + /// @inheritdoc IVaultApeStaking function unpause() external onlyPoolAdmin { _unpause(); } diff --git a/contracts/cross-chain/L1/VaultParaX.sol b/contracts/cross-chain/L1/VaultParaX.sol new file mode 100644 index 00000000..962c6cc8 --- /dev/null +++ b/contracts/cross-chain/L1/VaultParaX.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IERC721} from "../../dependencies/openzeppelin/contracts/IERC721.sol"; +import {Errors} from "../../protocol/libraries/helpers/Errors.sol"; +import "../../dependencies/openzeppelin/contracts/ReentrancyGuard.sol"; +import "../../dependencies/openzeppelin/contracts//Pausable.sol"; +import "./IParaxL1MessageHandler.sol"; +import "./IVaultParaX.sol"; +import {IDelegateRegistry} from "../../dependencies/delegation/IDelegateRegistry.sol"; + +contract VaultParaX is ReentrancyGuard, Pausable, IVaultParaX { + IParaxL1MessageHandler internal immutable l1MsgHander; + + IDelegateRegistry internal immutable delegationRegistry; + + mapping(address => bool) supportAsset; + + constructor( + IParaxL1MessageHandler msgHandler, + address _delegationRegistry + ) { + l1MsgHander = msgHandler; + delegationRegistry = IDelegateRegistry(_delegationRegistry); + } + + modifier onlyMsgHandler() { + require(msg.sender == address(l1MsgHander), Errors.ONLY_MSG_HANDLER); + _; + } + + function updateTokenDelegation( + address delegateTo, + address asset, + uint256[] calldata tokenIds, + bool value + ) external onlyMsgHandler { + uint256 length = tokenIds.length; + for (uint256 index = 0; index < length; index++) { + uint256 tokenId = tokenIds[index]; + delegationRegistry.delegateERC721( + delegateTo, + asset, + tokenId, + "", + value + ); + } + } +} diff --git a/contracts/cross-chain/L2/BridgeERC721.sol b/contracts/cross-chain/L2/BridgeERC721.sol deleted file mode 100644 index f8db4385..00000000 --- a/contracts/cross-chain/L2/BridgeERC721.sol +++ /dev/null @@ -1,47 +0,0 @@ -// 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); - } - } -} diff --git a/contracts/cross-chain/L2/BridgeERC721Handler.sol b/contracts/cross-chain/L2/BridgeERC721Handler.sol deleted file mode 100644 index 3f2627b6..00000000 --- a/contracts/cross-chain/L2/BridgeERC721Handler.sol +++ /dev/null @@ -1,34 +0,0 @@ -// 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 asset = getBridgeAsset[message.asset]; - require(asset != address(0), "invalid"); - - IBridgeERC721(asset).mint(message.receiver, message.tokenIds); - } -} diff --git a/contracts/cross-chain/L2/IBridgeERC721.sol b/contracts/cross-chain/L2/IBridgeERC721.sol deleted file mode 100644 index 327eb7b5..00000000 --- a/contracts/cross-chain/L2/IBridgeERC721.sol +++ /dev/null @@ -1,8 +0,0 @@ -// 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; -} diff --git a/contracts/cross-chain/L2/IParaxL2MessageHandler.sol b/contracts/cross-chain/L2/IParaxL2MessageHandler.sol index d2f4a190..5c954566 100644 --- a/contracts/cross-chain/L2/IParaxL2MessageHandler.sol +++ b/contracts/cross-chain/L2/IParaxL2MessageHandler.sol @@ -1,12 +1,11 @@ // 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 + address delegateTo, + address underlyingAsset, + uint256[] calldata tokenIds, + bool value ) external; } diff --git a/contracts/cross-chain/L2/ParaxL2MessageHandler.sol b/contracts/cross-chain/L2/ParaxL2MessageHandler.sol index bd41aa21..ea1e2e8d 100644 --- a/contracts/cross-chain/L2/ParaxL2MessageHandler.sol +++ b/contracts/cross-chain/L2/ParaxL2MessageHandler.sol @@ -1,38 +1,45 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {MessageType, BridgeMessage} from "../BridgeDefine.sol"; -import "./BridgeERC721Handler.sol"; +import {MessageType, BridgeMessage, ERC721DelegationMessage} from "../BridgeDefine.sol"; +import {Errors} from "../../protocol/libraries/helpers/Errors.sol"; import "./IParaxL2MessageHandler.sol"; +import "../socket/ISocket.sol"; contract ParaxL2MessageHandler is IParaxL2MessageHandler { - BridgeERC21Handler internal immutable erc712Handler; - address immutable bridgeImpl; - address immutable paraX; + uint32 public immutable siblingChainSlug; + address public immutable socket; + address public immutable paraX; - constructor(BridgeERC21Handler handler) { - erc712Handler = handler; - } - - function bridgeReceive(BridgeMessage calldata message) external { - require(msg.sender == bridgeImpl, ""); - if (message.msgType == MessageType.BridgeERC721) { - BridgeERC721Message memory erc721Message = abi.decode( - message.data, - (BridgeERC721Message) - ); - erc712Handler.bridgeAsset(erc721Message); - } else {} + constructor(address bridge, address paraX_, uint32 siblingChainSlug_) { + socket = bridge; + paraX = paraX_; + siblingChainSlug = siblingChainSlug_; } function updateTokenDelegation( - ERC721DelegationMessage calldata delegationInfo + address delegateTo, + address underlyingAsset, + uint256[] calldata tokenIds, + bool value ) external { require(msg.sender == paraX, Errors.ONLY_PARAX); + ERC721DelegationMessage memory delegationInfo; + delegationInfo.asset = underlyingAsset; + delegationInfo.delegateTo = delegateTo; + delegationInfo.tokenIds = tokenIds; + delegationInfo.value = value; BridgeMessage memory message; message.msgType = MessageType.ERC721DELEGATION; message.data = abi.encode(delegationInfo); //send msg + ISocket(socket).outbound( + siblingChainSlug, + 150000, + "", + "", + abi.encode(message) + ); } } diff --git a/contracts/cross-chain/socket/IExecutionManager.sol b/contracts/cross-chain/socket/IExecutionManager.sol new file mode 100644 index 00000000..96de9678 --- /dev/null +++ b/contracts/cross-chain/socket/IExecutionManager.sol @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.0; + +/** + * @title Execution Manager Interface + * @dev This interface defines the functions for managing and executing transactions on external chains + * @dev It is also responsible for collecting all the socket fees, which can then be pulled by others + */ +interface IExecutionManager { + /** + * @notice Returns the executor of the packed message and whether the executor is authorized + * @param packedMessage The message packed with payload, fees and config + * @param sig The signature of the message + * @return The address of the executor and a boolean indicating if the executor is authorized + */ + function isExecutor( + bytes32 packedMessage, + bytes memory sig + ) external view returns (address, bool); + + /** + * @notice Pays the fees for executing a transaction on the external chain + * @dev This function is payable and assumes the socket is going to send correct amount of fees. + * @param minMsgGasLimit_ The minimum gas limit for the transaction + * @param payloadSize_ The payload size in bytes + * @param executionParams_ Extra params for execution + * @param transmissionParams_ Extra params for transmission + * @param siblingChainSlug_ Sibling chain identifier + * @param switchboardFees_ fee charged by switchboard for processing transaction + * @param verificationOverheadFees_ fee charged for verifying transaction + * @param transmitManager_ The transmitManager address + * @param switchboard_ The switchboard address + * @param maxPacketLength_ The maxPacketLength for the capacitor + */ + function payAndCheckFees( + uint256 minMsgGasLimit_, + uint256 payloadSize_, + bytes32 executionParams_, + bytes32 transmissionParams_, + uint32 siblingChainSlug_, + uint128 switchboardFees_, + uint128 verificationOverheadFees_, + address transmitManager_, + address switchboard_, + uint256 maxPacketLength_ + ) external payable returns (uint128, uint128); + + /** + * @notice Returns the minimum fees required for executing a transaction on the external chain + * @param minMsgGasLimit_ minMsgGasLimit_ + * @param siblingChainSlug_ The destination slug + * @return The minimum fees required for executing the transaction + */ + function getMinFees( + uint256 minMsgGasLimit_, + uint256 payloadSize_, + bytes32 executionParams_, + uint32 siblingChainSlug_ + ) external view returns (uint128); + + /** + * @notice function for getting the minimum fees required for executing and transmitting a cross-chain transaction + * @dev this function is called at source to calculate the execution cost. + * @param payloadSize_ byte length of payload. Currently only used to check max length, later on will be used for fees calculation. + * @param executionParams_ Can be used for providing extra information. Currently used for msgValue + * @param siblingChainSlug_ Sibling chain identifier + * @return minExecutionFee : Minimum fees required for executing the transaction + */ + function getExecutionTransmissionMinFees( + uint256 minMsgGasLimit_, + uint256 payloadSize_, + bytes32 executionParams_, + bytes32 transmissionParams_, + uint32 siblingChainSlug_, + address transmitManager_ + ) external view returns (uint128, uint128); + + /** + * @notice Updates the execution fees for an executor and message ID + * @param executor The executor address + * @param executionFees The execution fees to update + * @param msgId The ID of the message + */ + function updateExecutionFees( + address executor, + uint128 executionFees, + bytes32 msgId + ) external; + + /** + * @notice updates the transmission fee + * @param remoteChainSlug_ sibling chain identifier + * @param transmitMinFees_ transmission fees collected + */ + function setTransmissionMinFees( + uint32 remoteChainSlug_, + uint128 transmitMinFees_ + ) external; + + /** + * @notice sets the minimum execution fees required for executing at `siblingChainSlug_` + * @dev this function currently sets the price for a constant msg gas limit and payload size + * @param nonce_ incremental id to prevent signature replay + * @param siblingChainSlug_ sibling chain identifier + * @param executionFees_ total fees where price in destination native token is converted to source native tokens + * @param signature_ signature of fee updater + */ + function setExecutionFees( + uint256 nonce_, + uint32 siblingChainSlug_, + uint128 executionFees_, + bytes calldata signature_ + ) external; + + /** + * @notice sets the min limit for msg value for `siblingChainSlug_` + * @param nonce_ incremental id to prevent signature replay + * @param siblingChainSlug_ sibling chain identifier + * @param msgValueMinThreshold_ min msg value + * @param signature_ signature of fee updater + */ + function setMsgValueMinThreshold( + uint256 nonce_, + uint32 siblingChainSlug_, + uint256 msgValueMinThreshold_, + bytes calldata signature_ + ) external; + + /** + * @notice sets the max limit for msg value for `siblingChainSlug_` + * @param nonce_ incremental id to prevent signature replay + * @param siblingChainSlug_ sibling chain identifier + * @param msgValueMaxThreshold_ max msg value + * @param signature_ signature of fee updater + */ + function setMsgValueMaxThreshold( + uint256 nonce_, + uint32 siblingChainSlug_, + uint256 msgValueMaxThreshold_, + bytes calldata signature_ + ) external; + + /** + * @notice sets the relative token price for `siblingChainSlug_` + * @dev this function is expected to be called frequently to match the original prices + * @param nonce_ incremental id to prevent signature replay + * @param siblingChainSlug_ sibling chain identifier + * @param relativeNativeTokenPrice_ relative price + * @param signature_ signature of fee updater + */ + function setRelativeNativeTokenPrice( + uint256 nonce_, + uint32 siblingChainSlug_, + uint256 relativeNativeTokenPrice_, + bytes calldata signature_ + ) external; + + /** + * @notice called by socket while executing message to validate if the msg value provided is enough + * @param executionParams_ a bytes32 string where first byte gives param type (if value is 0 or not) + * and remaining bytes give the msg value needed + * @param msgValue_ msg.value to be sent with inbound + */ + function verifyParams( + bytes32 executionParams_, + uint256 msgValue_ + ) external view; + + /** + * @notice withdraws switchboard fees from contract + * @param siblingChainSlug_ withdraw fees corresponding to this slug + * @param amount_ withdraw amount + */ + function withdrawSwitchboardFees( + uint32 siblingChainSlug_, + address switchboard_, + uint128 amount_ + ) external; + + /** + * @dev this function gets the transmitManager address from the socket contract. If it is ever upgraded in socket, + * @dev remove the fees from executionManager first, and then upgrade address at socket. + * @notice withdraws transmission fees from contract + * @param siblingChainSlug_ withdraw fees corresponding to this slug + * @param amount_ withdraw amount + */ + function withdrawTransmissionFees( + uint32 siblingChainSlug_, + uint128 amount_ + ) external; +} diff --git a/contracts/cross-chain/socket/ISocket.sol b/contracts/cross-chain/socket/ISocket.sol new file mode 100644 index 00000000..150eecc4 --- /dev/null +++ b/contracts/cross-chain/socket/ISocket.sol @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.0; + +import "./ITransmitManager.sol"; +import "./IExecutionManager.sol"; + +/** + * @title ISocket + * @notice An interface for a cross-chain communication contract + * @dev This interface provides methods for transmitting and executing messages between chains, + * connecting a plug to a remote chain and setting up switchboards for the message transmission + * This interface also emits events for important operations such as message transmission, execution status, + * and plug connection + */ +interface ISocket { + /** + * @notice A struct containing fees required for message transmission and execution + * @param transmissionFees fees needed for transmission + * @param switchboardFees fees needed by switchboard + * @param executionFee fees needed for execution + */ + struct Fees { + uint128 transmissionFees; + uint128 executionFee; + uint128 switchboardFees; + } + + /** + * @title MessageDetails + * @dev This struct defines the details of a message to be executed in a Decapacitor contract. + */ + struct MessageDetails { + // A unique identifier for the message. + bytes32 msgId; + // The fee to be paid for executing the message. + uint256 executionFee; + // The min amount of gas that can be used to execute the message. + uint256 minMsgGasLimit; + // The extra params which might provide msg value and additional info needed for message exec + bytes32 executionParams; + // The payload data to be executed in the message. + bytes payload; + } + + /** + * @title ExecutionDetails + * @dev This struct defines the execution details + */ + struct ExecutionDetails { + // packet id + bytes32 packetId; + // proposal count + uint256 proposalCount; + // gas limit needed to execute inbound + uint256 executionGasLimit; + // proof data required by the Decapacitor contract to verify the message's authenticity + bytes decapacitorProof; + // signature of executor + bytes signature; + } + + /** + * @notice emits the status of message after inbound call + * @param msgId msg id which is executed + */ + event ExecutionSuccess(bytes32 msgId); + + /** + * @notice emits the config set by a plug for a remoteChainSlug + * @param plug address of plug on current chain + * @param siblingChainSlug sibling chain slug + * @param siblingPlug address of plug on sibling chain + * @param inboundSwitchboard inbound switchboard (select from registered options) + * @param outboundSwitchboard outbound switchboard (select from registered options) + * @param capacitor capacitor selected based on outbound switchboard + * @param decapacitor decapacitor selected based on inbound switchboard + */ + event PlugConnected( + address plug, + uint32 siblingChainSlug, + address siblingPlug, + address inboundSwitchboard, + address outboundSwitchboard, + address capacitor, + address decapacitor + ); + + /** + * @notice registers a message + * @dev Packs the message and includes it in a packet with capacitor + * @param remoteChainSlug_ the remote chain slug + * @param minMsgGasLimit_ the gas limit needed to execute the payload on remote + * @param payload_ the data which is needed by plug at inbound call on remote + */ + function outbound( + uint32 remoteChainSlug_, + uint256 minMsgGasLimit_, + bytes32 executionParams_, + bytes32 transmissionParams_, + bytes calldata payload_ + ) external payable returns (bytes32 msgId); + + /** + * @notice executes a message + * @param executionDetails_ the packet details, proof and signature needed for message execution + * @param messageDetails_ the message details + */ + function execute( + ISocket.ExecutionDetails calldata executionDetails_, + ISocket.MessageDetails calldata messageDetails_ + ) external payable; + + /** + * @notice seals data in capacitor for specific batchSize + * @param batchSize_ size of batch to be sealed + * @param capacitorAddress_ address of capacitor + * @param signature_ signed Data needed for verification + */ + function seal( + uint256 batchSize_, + address capacitorAddress_, + bytes calldata signature_ + ) external payable; + + /** + * @notice proposes a packet + * @param packetId_ packet id + * @param root_ root data + * @param switchboard_ The address of switchboard for which this packet is proposed + * @param signature_ signed Data needed for verification + */ + function proposeForSwitchboard( + bytes32 packetId_, + bytes32 root_, + address switchboard_, + bytes calldata signature_ + ) external payable; + + /** + * @notice sets the config specific to the plug + * @param siblingChainSlug_ the sibling chain slug + * @param siblingPlug_ address of plug present at sibling chain to call inbound + * @param inboundSwitchboard_ the address of switchboard to use for receiving messages + * @param outboundSwitchboard_ the address of switchboard to use for sending messages + */ + function connect( + uint32 siblingChainSlug_, + address siblingPlug_, + address inboundSwitchboard_, + address outboundSwitchboard_ + ) external; + + /** + * @notice deploy capacitor and decapacitor for a switchboard with a specified max packet length, sibling chain slug, and capacitor type. + * @param siblingChainSlug_ The slug of the sibling chain that the switchboard is registered with. + * @param maxPacketLength_ The maximum length of a packet allowed by the switchboard. + * @param capacitorType_ The type of capacitor that the switchboard uses. + * @param siblingSwitchboard_ The switchboard address deployed on `siblingChainSlug_` + */ + function registerSwitchboardForSibling( + uint32 siblingChainSlug_, + uint256 maxPacketLength_, + uint256 capacitorType_, + address siblingSwitchboard_ + ) external returns (address capacitor, address decapacitor); + + /** + * @notice Emits the sibling switchboard for given `siblingChainSlug_`. + * @dev This function is expected to be only called by switchboard. + * @dev the event emitted is tracked by transmitters to decide which switchboard a packet should be proposed on + * @param siblingChainSlug_ The slug of the sibling chain + * @param siblingSwitchboard_ The switchboard address deployed on `siblingChainSlug_` + */ + function useSiblingSwitchboard( + uint32 siblingChainSlug_, + address siblingSwitchboard_ + ) external; + + /** + * @notice Retrieves the packet id roots for a specified packet id. + * @param packetId_ The packet id for which to retrieve the root. + * @param proposalCount_ The proposal id for packetId_ for which to retrieve the root. + * @param switchboard_ The address of switchboard for which this packet is proposed + * @return The packet id roots for the specified packet id. + */ + function packetIdRoots( + bytes32 packetId_, + uint256 proposalCount_, + address switchboard_ + ) external view returns (bytes32); + + /** + * @notice Retrieves the latest proposalCount for a packet id. + * @return The proposal count for the specified packet id. + */ + function proposalCount(bytes32 packetId_) external view returns (uint256); + + /** + * @notice Retrieves the minimum fees required for a message with a specified gas limit and destination chain. + * @param minMsgGasLimit_ The gas limit of the message. + * @param remoteChainSlug_ The slug of the destination chain for the message. + * @param plug_ The address of the plug through which the message is sent. + * @return totalFees The minimum fees required for the specified message. + */ + function getMinFees( + uint256 minMsgGasLimit_, + uint256 payloadSize_, + bytes32 executionParams_, + bytes32 transmissionParams_, + uint32 remoteChainSlug_, + address plug_ + ) external view returns (uint256 totalFees); + + /// return instance of transmit manager + function transmitManager__() external view returns (ITransmitManager); + + /// return instance of execution manager + function executionManager__() external view returns (IExecutionManager); +} diff --git a/contracts/cross-chain/socket/ITransmitManager.sol b/contracts/cross-chain/socket/ITransmitManager.sol new file mode 100644 index 00000000..46cb454c --- /dev/null +++ b/contracts/cross-chain/socket/ITransmitManager.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.0; + +/** + * @title ITransmitManager + * @dev The interface for a transmit manager contract + */ +interface ITransmitManager { + /** + * @notice Checks if a given transmitter is authorized to send transactions to the destination chain. + * @param siblingSlug The unique identifier for the sibling chain. + * @param digest The digest of the message being signed. + * @param signature The signature of the message being signed. + * @return The address of the transmitter and a boolean indicating whether the transmitter is authorized or not. + */ + function checkTransmitter( + uint32 siblingSlug, + bytes32 digest, + bytes calldata signature + ) external view returns (address, bool); + + /** + * @notice sets the transmission fee needed to transmit message to given `siblingSlug_` + * @dev recovered address should add have feeUpdater role for `siblingSlug_` + * @param nonce_ The incremental nonce to prevent signature replay + * @param siblingSlug_ sibling id for which fee updater is registered + * @param transmissionFees_ digest which is signed by transmitter + * @param signature_ signature + */ + function setTransmissionFees( + uint256 nonce_, + uint32 siblingSlug_, + uint128 transmissionFees_, + bytes calldata signature_ + ) external; + + /** + * @notice receives fees from Execution manager + * @dev this function can be used to keep track of fees received for each slug + * @param siblingSlug_ sibling id for which fee updater is registered + */ + function receiveFees(uint32 siblingSlug_) external payable; +} diff --git a/contracts/protocol/pool/PoolCrossChain.sol b/contracts/protocol/pool/PoolCrossChain.sol new file mode 100644 index 00000000..90f13ae0 --- /dev/null +++ b/contracts/protocol/pool/PoolCrossChain.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.10; + +import {ParaVersionedInitializable} from "../libraries/paraspace-upgradeability/ParaVersionedInitializable.sol"; +import {Errors} from "../libraries/helpers/Errors.sol"; +import {DataTypes} from "../libraries/types/DataTypes.sol"; +import {IPoolAddressesProvider} from "../../interfaces/IPoolAddressesProvider.sol"; +import {IPoolCrossChain} from "../../interfaces/IPoolCrossChain.sol"; +import {PoolStorage} from "./PoolStorage.sol"; +import {Address} from "../../dependencies/openzeppelin/contracts/Address.sol"; +import {ParaReentrancyGuard} from "../libraries/paraspace-upgradeability/ParaReentrancyGuard.sol"; +import "../../cross-chain/L2/IParaxL2MessageHandler.sol"; + +/** + * @title Pool Parameters contract + * + * @notice Main point of interaction with an ParaSpace protocol's market + **/ +contract PoolCrossChain is + ParaVersionedInitializable, + ParaReentrancyGuard, + PoolStorage, + IPoolCrossChain +{ + uint256 public constant POOL_REVISION = 200; + IPoolAddressesProvider public immutable ADDRESSES_PROVIDER; + address public immutable CROSS_CHAIN_MSG_HANDLER; + + function getRevision() internal pure virtual override returns (uint256) { + return POOL_REVISION; + } + + /** + * @dev Constructor. + * @param provider The address of the PoolAddressesProvider contract + * @param msgHandler The address of the L2 message handler contract + */ + constructor(IPoolAddressesProvider provider, address msgHandler) { + ADDRESSES_PROVIDER = provider; + CROSS_CHAIN_MSG_HANDLER = msgHandler; + } + + function updateTokenDelegation( + address delegateTo, + address underlyingAsset, + uint256[] calldata tokenIds, + bool value + ) external { + DataTypes.PoolStorage storage ps = poolStorage(); + + require( + msg.sender == ps._reserves[underlyingAsset].xTokenAddress, + Errors.CALLER_NOT_XTOKEN + ); + + IParaxL2MessageHandler(CROSS_CHAIN_MSG_HANDLER).updateTokenDelegation( + delegateTo, + underlyingAsset, + tokenIds, + value + ); + } +} diff --git a/contracts/protocol/pool/PoolParameters.sol b/contracts/protocol/pool/PoolParameters.sol index 4a8d53cb..7366d1bb 100644 --- a/contracts/protocol/pool/PoolParameters.sol +++ b/contracts/protocol/pool/PoolParameters.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.10; import {ParaVersionedInitializable} from "../libraries/paraspace-upgradeability/ParaVersionedInitializable.sol"; -import {Errors} from "../libraries/helpers/Errors.sol"; import {ReserveConfiguration} from "../libraries/configuration/ReserveConfiguration.sol"; import {PoolLogic} from "../libraries/logic/PoolLogic.sol"; import {ReserveLogic} from "../libraries/logic/ReserveLogic.sol"; diff --git a/contracts/protocol/tokenization/base/MintableIncentivizedERC721.sol b/contracts/protocol/tokenization/base/MintableIncentivizedERC721.sol index d4796447..ae388175 100644 --- a/contracts/protocol/tokenization/base/MintableIncentivizedERC721.sol +++ b/contracts/protocol/tokenization/base/MintableIncentivizedERC721.sol @@ -397,10 +397,6 @@ abstract contract MintableIncentivizedERC721 is ); } - function revokeDelegation(address v1Registry) external onlyPoolAdmin { - IDelegationRegistry(v1Registry).revokeAllDelegates(); - } - function delegateForToken( address delegate, uint256[] calldata tokenIds,