Skip to content

Commit

Permalink
Adjust current bridge api to an nft bridge version
Browse files Browse the repository at this point in the history
  • Loading branch information
adaki2004 committed Jul 6, 2023
1 parent 5cd6c82 commit 109e22e
Show file tree
Hide file tree
Showing 8 changed files with 982 additions and 0 deletions.
284 changes: 284 additions & 0 deletions packages/protocol/contracts/nft_bridge/Erc721Bridge.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
// SPDX-License-Identifier: MIT
// _____ _ _ _ _
// |_ _|_ _(_) |_____ | | __ _| |__ ___
// | |/ _` | | / / _ \ | |__/ _` | '_ (_-<
// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/

pragma solidity ^0.8.20;

import { AddressResolver } from "../common/AddressResolver.sol";
import { EssentialContract } from "../common/EssentialContract.sol";
import { Proxied } from "../common/Proxied.sol";
import { IErc721Bridge } from "./erc721/IErc721Bridge.sol";
import { NftBridgeErrors } from "./NftBridgeErrors.sol";
import { LibErc721BridgeData } from "./erc721/libs/LibErc721BridgeData.sol";
// import { LibBridgeProcess } from "./libs/LibBridgeProcess.sol";
// import { LibBridgeRelease } from "./libs/LibBridgeRelease.sol";
// import { LibBridgeRetry } from "./libs/LibBridgeRetry.sol";
import { LibErc721BridgeSend } from "./erc721/libs/LibErc721BridgeSend.sol";
import { LibErc721BridgeStatus } from "./erc721/libs/LibErc721BridgeStatus.sol";

/**
* This contract is an ERC-721 token bridge contract which is deployed on both L1 and L2.
* which calls the library implementations. See _IErc721Bridge_ for more details.
* @dev The code hash for the same address on L1 and L2 may be different.
* @custom:security-contact [email protected]
*/
contract Erc721Bridge is EssentialContract, IErc721Bridge, NftBridgeErrors {
using LibErc721BridgeData for Message;

LibErc721BridgeData.State private _state; // 50 slots reserved

event MessageStatusChanged(
bytes32 indexed msgHash,
LibErc721BridgeStatus.MessageStatus status,
address transactor
);

event DestChainEnabled(uint256 indexed chainId, bool enabled);

/**
* Initializer to be called after being deployed behind a proxy.
* @dev Initializer function to setup the EssentialContract.
* @param _addressManager The address of the AddressManager contract.
*/
function init(address _addressManager) external initializer {
EssentialContract._init(_addressManager);
}

/**
* Sends a message from the current chain to the destination chain specified
* in the message.
* @dev Sends a message by calling the LibErc721BridgeSend.sendMessageErc721 library
* function.
* @param message The message to send. (See IBridge)
* @return msgHash The hash of the message that was sent.
*/
function sendMessageErc721(Message calldata message)
external
payable
nonReentrant
returns (bytes32 msgHash)
{
return LibErc721BridgeSend.sendMessageErc721({
state: _state,
resolver: AddressResolver(this),
message: message
});
}

// TODO: Implement them gradually
/**
* Releases the Ether locked in the bridge as part of a cross-chain
* transfer.
* @dev Releases the Ether by calling the LibBridgeRelease.releaseEther
* library function.
* @param message The message containing the details of the Ether transfer.
* (See IBridge)
* @param proof The proof of the cross-chain transfer.
*/
function releaseTokenErc721(
IErc721Bridge.Message calldata message,
bytes calldata proof
)
external
nonReentrant
{
return;
// TODO: Implement
// return LibBridgeRelease.releaseEther({
// state: _state,
// resolver: AddressResolver(this),
// message: message,
// proof: proof
// });
}

// /**
// * Processes a message received from another chain.
// * @dev Processes the message by calling the LibBridgeProcess.processMessage
// * library function.
// * @param message The message to process.
// * @param proof The proof of the cross-chain transfer.
// */
// function processMessage(
// Message calldata message,
// bytes calldata proof
// )
// external
// nonReentrant
// {
// return LibBridgeProcess.processMessage({
// state: _state,
// resolver: AddressResolver(this),
// message: message,
// proof: proof
// });
// }

// /**
// * Retries sending a message that previously failed to send.
// * @dev Retries the message by calling the LibBridgeRetry.retryMessage
// * library function.
// * @param message The message to retry.
// * @param isLastAttempt Specifies whether this is the last attempt to send
// * the message.
// */
// function retryMessage(
// Message calldata message,
// bool isLastAttempt
// )
// external
// nonReentrant
// {
// return LibBridgeRetry.retryMessage({
// state: _state,
// resolver: AddressResolver(this),
// message: message,
// isLastAttempt: isLastAttempt
// });
// }

/**
* Check if the message with the given hash has been sent.
* @param msgHash The hash of the message.
* @return Returns true if the message has been sent, false otherwise.
*/
function isMessageSentErc721(bytes32 msgHash)
public
view
virtual
returns (bool)
{
return LibErc721BridgeSend.isMessageSentErc721(AddressResolver(this), msgHash);
}

/**
* Check if the message with the given hash has been received.
* @param msgHash The hash of the message.
* @param srcChainId The source chain ID.
* @param proof The proof of message receipt.
* @return Returns true if the message has been received, false otherwise.
*/
function isMessageReceivedErc721(
bytes32 msgHash,
uint256 srcChainId,
bytes calldata proof
)
public
view
virtual
override
returns (bool)
{
return LibErc721BridgeSend.isMessageReceivedErc721({
resolver: AddressResolver(this),
msgHash: msgHash,
srcChainId: srcChainId,
proof: proof
});
}

/**
* Check if the message with the given hash has failed.
* @param msgHash The hash of the message.
* @param destChainId The destination chain ID.
* @param proof The proof of message failure.
* @return Returns true if the message has failed, false otherwise.
*/
function isMessageFailedErc721(
bytes32 msgHash,
uint256 destChainId,
bytes calldata proof
)
public
view
virtual
override
returns (bool)
{
return LibErc721BridgeStatus.isMessageFailedErc721({
resolver: AddressResolver(this),
msgHash: msgHash,
destChainId: destChainId,
proof: proof
});
}

/**
* Get the status of the message with the given hash.
* @param msgHash The hash of the message.
* @return Returns the status of the message.
*/
function getMessageStatusErc721(bytes32 msgHash)
public
view
virtual
returns (LibErc721BridgeStatus.MessageStatus)
{
return LibErc721BridgeStatus.getMessageStatusErc721(msgHash);
}

/**
* Get the current context
* @return Returns the current context.
*/
function context() public view returns (Context memory) {
return _state.ctx;
}

// /**
// * Check if the Ether associated with the given message hash has been
// * released.
// * @param msgHash The hash of the message.
// * @return Returns true if the Ether has been released, false otherwise.
// */
// function isEtherReleased(bytes32 msgHash) public view returns (bool) {
// return _state.etherReleased[msgHash];
// }

/**
* Check if the destination chain with the given ID is enabled.
* @param _chainId The ID of the chain.
* @return enabled Returns true if the destination chain is enabled, false
* otherwise.
*/

function isDestChainEnabled(uint256 _chainId)
public
view
returns (bool enabled)
{
(enabled,) =
LibErc721BridgeSend.isDestChainEnabled(AddressResolver(this), _chainId);
}

/**
* Compute the hash of a given message.
* @param message The message to compute the hash for.
* @return Returns the hash of the message.
*/
function hashMessage(Message calldata message)
public
pure
override
returns (bytes32)
{
return LibErc721BridgeData.hashMessage(message);
}

/**
* Get the slot associated with a given message hash status.
* @param msgHash The hash of the message.
* @return Returns the slot associated with the given message hash status.
*/
function getMessageStatusSlot(bytes32 msgHash)
public
pure
returns (bytes32)
{
return LibErc721BridgeStatus.getMessageStatusSlot(msgHash);
}
}

contract ProxiedErc721Bridge is Proxied, Erc721Bridge { }
111 changes: 111 additions & 0 deletions packages/protocol/contracts/nft_bridge/Erc721Vault.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// SPDX-License-Identifier: MIT
// _____ _ _ _ _
// |_ _|_ _(_) |_____ | | __ _| |__ ___
// | |/ _` | | / / _ \ | |__/ _` | '_ (_-<
// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/

pragma solidity ^0.8.20;

import { IERC721ReceiverUpgradeable } from
"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol";
import { IERC721Upgradeable} from
"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import { Create2Upgradeable } from
"@openzeppelin/contracts-upgradeable/utils/Create2Upgradeable.sol";
import { EssentialContract } from "../common/EssentialContract.sol";
import { Proxied } from "../common/Proxied.sol";
import { LibAddress } from "../libs/LibAddress.sol";
import { NftBridgeErrors } from "./NftBridgeErrors.sol";

/**
* This contract is for vaulting (and releasing) ERC721 tokens
* @dev Only the contract owner can authorize or deauthorize addresses.
* @custom:security-contact [email protected]
*/
contract Erc721Vault is EssentialContract, NftBridgeErrors, IERC721ReceiverUpgradeable {
using LibAddress for address;

// Maps contract to a contract on a different chain
struct ContractMapping {
address sisterContract;
string tokenName;
string tokenSymbol;
mapping (uint256 tokenId => bool inVault) tokenInVault;
}
mapping(address tokenContract => ContractMapping wrappedTokenContract) originalToWrapperData;

mapping(address addr => bool isAuthorized) private _authorizedAddrs;
uint256[49] private __gap;

event Authorized(address indexed addr, bool authorized);
event TokensReleased(address indexed to, address contractAddress, uint256[] tokenIds);

modifier onlyAuthorized() {
if (!isAuthorized(msg.sender)) {
revert ERC721_TV_NOT_AUTHORIZED();
}
_;
}

/**
* Initialize the contract with an address manager
* @param addressManager The address of the address manager
*/
function init(address addressManager) external initializer {
EssentialContract._init(addressManager);
}

/**
* Transfer token(s) from Erc721Vault to a designated address, checking that the
* sender is authorized.
* @param recipient Address to receive Ether.
* @param tokenContract Token contract.
* @param tokenIds Array of tokenIds to be sent
*/
function releaseTokens(
address recipient,
address tokenContract,
uint256[] memory tokenIds
)
public
onlyAuthorized
nonReentrant
{
if (recipient == address(0)) {
revert ERC721_TV_DO_NOT_BURN();
}

for (uint256 i; i < tokenIds.length; i++) {
IERC721Upgradeable(tokenContract).safeTransferFrom(address(this), recipient, tokenIds[i]);
}

emit TokensReleased(recipient, tokenContract, tokenIds);
}

/**
* Set the authorized status of an address, only the owner can call this.
* @param addr Address to set the authorized status of.
* @param authorized Authorized status to set.
*/
function authorize(address addr, bool authorized) public onlyOwner {
if (addr == address(0) || _authorizedAddrs[addr] == authorized) {
revert ERC721_B_TV_PARAM();
}
_authorizedAddrs[addr] = authorized;
emit Authorized(addr, authorized);
}

/**
* Get the authorized status of an address.
* @param addr Address to get the authorized status of.
*/
function isAuthorized(address addr) public view returns (bool) {
return _authorizedAddrs[addr];
}

function onERC721Received(address, address, uint256, bytes calldata ) external pure returns (bytes4) {
return IERC721ReceiverUpgradeable.onERC721Received.selector;
}
}

contract ProxiedErc721Vault is Proxied, Erc721Vault { }
Loading

0 comments on commit 109e22e

Please sign in to comment.