Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/aavegotchi #155

Draft
wants to merge 62 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
e09004e
feat: add NFT bridge
orionstardust Sep 2, 2024
47bfac2
feat:add new cli for new NFT project
orionstardust Sep 2, 2024
ba9739a
fix: lint
orionstardust Sep 2, 2024
96758e0
feat: add script for new NFT project
orionstardust Sep 4, 2024
82d66f1
fix
orionstardust Sep 6, 2024
d3ad866
feat: add deploy script for NFT Superbridge
orionstardust Sep 6, 2024
9dd3ce6
feat: add totalMinted for new NFT project
orionstardust Sep 11, 2024
e53dbfa
feat: add interface for NFT metadata
orionstardust Sep 19, 2024
95dae49
fix: nft bridge
orionstardust Sep 20, 2024
bacb3fe
fix: build
orionstardust Sep 24, 2024
b9b6126
Merge remote-tracking branch 'refs/remotes/origin/main' into feat/nft
orionstardust Sep 24, 2024
ea76c43
Merge remote-tracking branch 'refs/remotes/origin/main' into feat/nft
orionstardust Sep 25, 2024
18626ad
fix: issues
orionstardust Sep 27, 2024
da29b9b
feat: add script for new NFT project
orionstardust Sep 27, 2024
49ee3e9
fix: redeploy
orionstardust Oct 1, 2024
9702a59
fix: deployed addresses
orionstardust Oct 1, 2024
de1df13
fix: deployed addresses
orionstardust Oct 1, 2024
46d379e
fix: mint wearables
orionstardust Oct 16, 2024
a023804
Merge branch 'SocketDotTech:main' into feat/nft
cinnabarhorse Oct 24, 2024
5ccf110
chore: work on wrapping supertoken
cinnabarhorse Oct 25, 2024
718f4c8
chore: work on wrapping supertoken
cinnabarhorse Oct 25, 2024
e8a640c
chore: begin adding Unwrap hook
cinnabarhorse Oct 25, 2024
e5cb07e
chore: adding unwrapsupertoken, revert Supertoken.sol
cinnabarhorse Oct 25, 2024
3566e46
Update SuperToken.sol
cinnabarhorse Oct 25, 2024
3684045
Revert "fix: mint wearables"
orionstardust Oct 26, 2024
7db2e4a
Merge branch 'refs/heads/feat/nft' into feat/wraptoken
orionstardust Oct 26, 2024
e9f93d2
fix: unwrap hook and erc20 interface
orionstardust Oct 26, 2024
ba1d156
chore: working on unwrap supertoken
cinnabarhorse Oct 26, 2024
6842a17
chore: remove files
cinnabarhorse Oct 26, 2024
ef67a55
Delete socket_ghst2_testnet.ts
cinnabarhorse Oct 26, 2024
333439b
chore: working on unwrap
cinnabarhorse Oct 26, 2024
bc94111
investigating failed deployment
cinnabarhorse Oct 26, 2024
5d0ca91
chore: add addresses
cinnabarhorse Oct 26, 2024
e7c1fbe
chore: update hook
cinnabarhorse Oct 26, 2024
0b9bad3
chore: add addresses
cinnabarhorse Oct 26, 2024
5b7303f
Update UnwrapHook.sol
cinnabarhorse Oct 26, 2024
f132a34
fix: unwrap hook and erc20 interface
orionstardust Oct 26, 2024
d2b0d1f
chore: update scripts
cinnabarhorse Oct 27, 2024
eeceb25
chore: update addresses
cinnabarhorse Oct 27, 2024
e07cc29
chore: hook is working
cinnabarhorse Oct 27, 2024
dce0019
chore: prep unwrap supertoken
cinnabarhorse Oct 28, 2024
0fb48d7
chore: add checks and documentation
cinnabarhorse Oct 28, 2024
129b19a
chore: update pre hook
cinnabarhorse Oct 28, 2024
591c1f2
fix: unwrap hook and erc20 interface
orionstardust Oct 29, 2024
060a89f
fix: issues in wrap hook
orionstardust Oct 29, 2024
5ed3ca3
fix: remove wrap hook
orionstardust Oct 29, 2024
0af169c
fix: rollback for wrap hook
orionstardust Oct 31, 2024
92aeecd
feat: add fee logic of bridging to hook
orionstardust Oct 31, 2024
ad3d5e0
fix: fee hook and test
orionstardust Oct 31, 2024
cbd5be3
fix: update fee hook and test
orionstardust Oct 31, 2024
261c588
fix: update fee hook and test
orionstardust Nov 1, 2024
d019431
fix: test gotchi and items
orionstardust Nov 4, 2024
dd2d9b4
add test/prod USDC and cleanup
cinnabarhorse Nov 7, 2024
153df4c
chore: formatting
cinnabarhorse Nov 7, 2024
c53a96e
chore: add SGHST on mainnet and cleanup
cinnabarhorse Nov 7, 2024
6134452
chore: formatting
cinnabarhorse Nov 7, 2024
139dd1c
chore: add scripts
cinnabarhorse Nov 7, 2024
0c9569f
Update setHook.ts
cinnabarhorse Nov 9, 2024
2666ab0
Merge branch 'feat/nft' into feat/wraptoken
cinnabarhorse Nov 9, 2024
c9f45df
chore: add base support
cinnabarhorse Nov 13, 2024
d84c29e
chore: formatting
cinnabarhorse Nov 13, 2024
093eb44
chore: update usdc params
cinnabarhorse Nov 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
359 changes: 359 additions & 0 deletions contracts/bridge/NFT/NFTBase.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,359 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "solmate/utils/ReentrancyGuard.sol";
import "solmate/tokens/ERC721.sol";
import "solmate/tokens/ERC1155.sol";
import {IConnector} from "../../interfaces/IConnector.sol";
import "../../interfaces/INFTHook.sol";
import "../../interfaces/INFTBridge.sol";
import "../../interfaces/INFTMetadata.sol";
import "../../common/Errors.sol";
import "../../common/Constants.sol";
import "../../utils/AccessControl.sol";

abstract contract NFTBase is
ReentrancyGuard,
INFTBridge,
ERC721TokenReceiver,
ERC1155TokenReceiver,
AccessControl
{
address public immutable token;
bytes32 public bridgeType;
INFTHook public hook__;
// message identifier => cache
mapping(bytes32 => bytes) public identifierCache;

// connector => cache
mapping(address => bytes) public connectorCache;

mapping(address => bool) public validConnectors;

event ConnectorStatusUpdated(address connector, bool status);

event HookUpdated(address newHook);

event BridgingTokens(
address connector,
address sender,
address receiver,
uint256 tokenId,
uint256 amount,
bytes32 messageId
);
event TokensBridged(
address connecter,
address receiver,
uint256 tokenId,
uint256 amount,
bytes32 messageId
);

constructor(address token_) AccessControl(msg.sender) {
if (token_ != ETH_ADDRESS && token_.code.length == 0)
revert InvalidTokenContract();
token = token_;
}

/**
* @notice this function is used to update hook
* @dev it can only be updated by owner
* @dev should be carefully migrated as it can risk user funds
* @param hook_ new hook address
*/
function updateHook(
address hook_,
bool approve_
) external virtual onlyOwner {
// remove the approval from the old hook
if (bridgeType == ERC721_VAULT) {
if (
ERC721(token).isApprovedForAll(address(this), address(hook__))
) {
ERC721(token).setApprovalForAll(address(hook__), false);
}
if (approve_) {
ERC721(token).setApprovalForAll(hook_, approve_);
}
} else {
if (
ERC1155(token).isApprovedForAll(address(this), address(hook__))
) {
ERC1155(token).setApprovalForAll(address(hook__), false);
}
if (approve_) {
ERC1155(token).setApprovalForAll(hook_, approve_);
}
}
hook__ = INFTHook(hook_);

emit HookUpdated(hook_);
}

function updateConnectorStatus(
address[] calldata connectors,
bool[] calldata statuses
) external onlyOwner {
uint256 length = connectors.length;
for (uint256 i; i < length; i++) {
validConnectors[connectors[i]] = statuses[i];
emit ConnectorStatusUpdated(connectors[i], statuses[i]);
}
}

/**
* @notice Executes pre-bridge operations before initiating a token bridge transfer.
* @dev This internal function is called before initiating a token bridge transfer.
* It validates the receiver address and the connector, and if a pre-hook contract is defined,
* it executes the source pre-hook call.
* @param connector_ The address of the connector responsible for the transfer.
* @param transferInfo_ Information about the transfer.
* @return transferInfo Information about the transfer after pre-bridge operations.
* @return postHookData Data returned from the pre-hook call.
* @dev Reverts with `ZeroAddressReceiver` if the receiver address is zero.
* Reverts with `InvalidConnector` if the connector address is not valid.
*/
function _beforeBridge(
address connector_,
NFTTransferInfo memory transferInfo_
)
internal
returns (NFTTransferInfo memory transferInfo, bytes memory postHookData)
{
if (transferInfo_.receiver == address(0)) revert ZeroAddressReceiver();
if (!validConnectors[connector_]) revert InvalidConnector();

if (address(hook__) != address(0)) {
(transferInfo, postHookData) = hook__.srcPreHookCall(
SrcPreHookNFTCallParams(connector_, msg.sender, transferInfo_)
);
} else {
transferInfo = transferInfo_;
}
}

/**
* @notice Executes post-bridge operations after completing a token bridge transfer.
* @dev This internal function is called after completing a token bridge transfer.
* It executes the source post-hook call if a hook contract is defined, calculates fees,
* calls the outbound function of the connector, and emits an event for tokens withdrawn.
* @param msgGasLimit_ The gas limit for the outbound call.
* @param connector_ The address of the connector responsible for the transfer.
* @param options_ Additional options for the outbound call.
* @param postHookData_ Data returned from the source post-hook call.
* @param transferInfo_ Information about the transfer.
* @dev Reverts with `MessageIdMisMatched` if the returned message ID does not match the expected message ID.
*/
function _afterBridge(
uint256 msgGasLimit_,
address connector_,
bytes memory options_,
bytes memory postHookData_,
NFTTransferInfo memory transferInfo_
) internal {
NFTTransferInfo memory transferInfo = transferInfo_;
if (address(hook__) != address(0)) {
transferInfo = hook__.srcPostHookCall(
SrcPostHookNFTCallParams(
connector_,
options_,
postHookData_,
transferInfo_
)
);
}

uint256 fees = msg.value;
bytes32 messageId = IConnector(connector_).getMessageId();
bytes32 returnedMessageId = IConnector(connector_).outbound{
value: fees
}(
msgGasLimit_,
abi.encode(
transferInfo.receiver,
transferInfo.tokenId,
transferInfo.amount,
messageId,
transferInfo.extraData
),
options_
);
if (returnedMessageId != messageId) revert MessageIdMisMatched();

emit BridgingTokens(
connector_,
msg.sender,
transferInfo.receiver,
transferInfo.tokenId,
transferInfo.amount,
messageId
);
}

/**
* @notice Executes pre-mint operations before minting tokens.
* @dev This internal function is called before minting tokens.
* It validates the caller as a valid connector, checks if the receiver is not this contract, the bridge contract,
* or the token contract, and executes the destination pre-hook call if a hook contract is defined.
* @param transferInfo_ Information about the transfer.
* @return postHookData Data returned from the destination pre-hook call.
* @return transferInfo Information about the transfer after pre-mint operations.
* @dev Reverts with `InvalidConnector` if the caller is not a valid connector.
* Reverts with `CannotTransferOrExecuteOnBridgeContracts` if the receiver is this contract, the bridge contract,
* or the token contract.
*/
function _beforeMint(
uint32,
NFTTransferInfo memory transferInfo_
)
internal
returns (bytes memory postHookData, NFTTransferInfo memory transferInfo)
{
if (!validConnectors[msg.sender]) revert InvalidConnector();

// no need of source check here, as if invalid caller, will revert with InvalidPoolId
if (
transferInfo_.receiver == address(this) ||
// transferInfo_.receiver == address(bridge__) ||
transferInfo_.receiver == token
) revert CannotTransferOrExecuteOnBridgeContracts();

if (address(hook__) != address(0)) {
(postHookData, transferInfo) = hook__.dstPreHookCall(
DstPreHookNFTCallParams(
msg.sender,
connectorCache[msg.sender],
transferInfo_
)
);
} else {
transferInfo = transferInfo_;
}
}

/**
* @notice Executes post-mint operations after minting tokens.
* @dev This internal function is called after minting tokens.
* It executes the destination post-hook call if a hook contract is defined and updates cache data.
* @param messageId_ The unique identifier for the mint transaction.
* @param postHookData_ Data returned from the destination pre-hook call.
* @param transferInfo_ Information about the mint transaction.
*/
function _afterMint(
uint256,
bytes32 messageId_,
bytes memory postHookData_,
NFTTransferInfo memory transferInfo_
) internal {
if (address(hook__) != address(0)) {
CacheData memory cacheData = hook__.dstPostHookCall(
DstPostHookNFTCallParams(
msg.sender,
messageId_,
connectorCache[msg.sender],
postHookData_,
transferInfo_
)
);

identifierCache[messageId_] = cacheData.identifierCache;
connectorCache[msg.sender] = cacheData.connectorCache;
}

if (transferInfo_.extraData.length > 0) {
INFTMetadata(token).setMetadata(
transferInfo_.tokenId,
transferInfo_.extraData
);
}

emit TokensBridged(
msg.sender,
transferInfo_.receiver,
transferInfo_.tokenId,
transferInfo_.amount,
messageId_
);
}

/**
* @notice Executes pre-retry operations before retrying a failed transaction.
* @dev This internal function is called before retrying a failed transaction.
* It validates the connector, retrieves cache data for the given message ID,
* and executes the pre-retry hook if defined.
* @param connector_ The address of the connector responsible for the failed transaction.
* @param messageId_ The unique identifier for the failed transaction.
* @return postHookData Data returned from the pre-retry hook call.
* @return transferInfo Information about the transfer.
* @dev Reverts with `InvalidConnector` if the connector is not valid.
* Reverts with `NoPendingData` if there is no pending data for the given message ID.
*/
function _beforeRetry(
address connector_,
bytes32 messageId_
)
internal
returns (bytes memory postHookData, NFTTransferInfo memory transferInfo)
{
if (!validConnectors[connector_]) revert InvalidConnector();

CacheData memory cacheData = CacheData(
identifierCache[messageId_],
connectorCache[connector_]
);

if (cacheData.identifierCache.length == 0) revert NoPendingData();
(postHookData, transferInfo) = hook__.preRetryHook(
PreRetryHookCallParams(connector_, cacheData)
);
}

/**
* @notice Executes post-retry operations after retrying a failed transaction.
* @dev This internal function is called after retrying a failed transaction.
* It retrieves cache data for the given message ID, executes the post-retry hook if defined,
* and updates cache data.
* @param connector_ The address of the connector responsible for the failed transaction.
* @param messageId_ The unique identifier for the failed transaction.
* @param postHookData Data returned from the pre-retry hook call.
*/
function _afterRetry(
address connector_,
bytes32 messageId_,
bytes memory postHookData
) internal {
CacheData memory cacheData = CacheData(
identifierCache[messageId_],
connectorCache[connector_]
);

(cacheData) = hook__.postRetryHook(
PostRetryHookCallParams(
connector_,
messageId_,
postHookData,
cacheData
)
);
identifierCache[messageId_] = cacheData.identifierCache;
connectorCache[connector_] = cacheData.connectorCache;
}

/**
* @notice Retrieves the minimum fees required for a transaction from a connector.
* @dev This function returns the minimum fees required for a transaction from the specified connector,
* based on the provided message gas limit and payload size.
* @param connector_ The address of the connector.
* @param msgGasLimit_ The gas limit for the transaction.
* @param payloadSize_ The size of the payload for the transaction.
* @return totalFees The total minimum fees required for the transaction.
*/
function getMinFees(
address connector_,
uint256 msgGasLimit_,
uint256 payloadSize_
) external view returns (uint256 totalFees) {
return IConnector(connector_).getMinFees(msgGasLimit_, payloadSize_);
}
}
Loading