Skip to content

Commit

Permalink
Merge pull request #2 from 0xdevhub/fix/refactoring
Browse files Browse the repository at this point in the history
Fix/refactoring
  • Loading branch information
wellitongervickas authored Dec 6, 2023
2 parents 27a8ed4 + 160e78e commit 55ded95
Show file tree
Hide file tree
Showing 35 changed files with 3,753 additions and 844 deletions.
8 changes: 0 additions & 8 deletions config/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ export const avalancheFuji: Chain = {
}
},
testnet: true,
crosschain: {
gasRequiredDeploy: 1299614n,
gasRequiredToMint: 95639n
},
assets: {
LINK: {
address: '0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846',
Expand Down Expand Up @@ -86,10 +82,6 @@ export const polygonMumbai: Chain = {
}
},
testnet: true,
crosschain: {
gasRequiredDeploy: 1300024n,
gasRequiredToMint: 95639n
},
assets: {
LINK: {
address: '0x326C977E6efc84E512bB9C30f76E30c160eD06FB',
Expand Down
5 changes: 1 addition & 4 deletions config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ export interface Chain {
}
}
testnet: boolean
crosschain: {
gasRequiredToMint: bigint
gasRequiredDeploy: bigint
}

assets: {
[key: string]: {
address: string
Expand Down
22 changes: 17 additions & 5 deletions contracts-left.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,34 @@ pnpm hardhat deploy-bridge-contract --network 80001

=========================

pnpm hardhat deploy-adapter-contract --network 80001 --adapter "CCIPAdapter" --bridge-address 0x89d50fBE79D31CBF1d9661f411C7865b611AC6f9 --router-address 0x70499c328e1e2a3c41108bd3730f6670a44595d1 --fee-token-name LINK
pnpm hardhat deploy-adapter-contract --network 80001 --adapter "CCIPAdapter" --bridge-address 0xAC4c62F5aeBfc879AeB4A3b919be608980E73D56 --router-address 0x70499c328e1e2a3c41108bd3730f6670a44595d1 --fee-token-name LINK

# Set chain settings

=========================

pnpm hardhat set-chain-settings --network 80001 --bridge-address 0x89d50fBE79D31CBF1d9661f411C7865b611AC6f9 --evm-chain-id 43113 --non-evm-chain-id 14767482510784806043 --adapter-address 0xaE784bC30BC8D29f9493a4366137bF371775159f ---target-adapter-address 0x940D6921A7931AFB07107323118F2151DCBCF2eC --is-enabled true --gas-limit 4000000
pnpm hardhat set-chain-settings --network 80001 --bridge-address 0xAC4c62F5aeBfc879AeB4A3b919be608980E73D56 --evm-chain-id 43113 --non-evm-chain-id 14767482510784806043 --adapter-address 0x45ACa774719B311fF4DA05724866DdBC18f3e31c ---target-adapter-address 0x01Dfab90DC8C8E5F66E3fB51009B4c5D8820e44f --is-enabled true --gas-limit 4000000

# Bridge ERC721 using ERC20 token as fee

=========================

pnpm hardhat bridge-erc721-using-erc20 --network 80001 --token-name "hello" --token-symbol "world" --bridge-address 0xAC4c62F5aeBfc879AeB4A3b919be608980E73D56 --adapter-address 0x45ACa774719B311fF4DA05724866DdBC18f3e31c --target-network 43113 --fee-token-name LINK

# Execute

pnpm hardhat execute-message --network 80001 --adapter-address 0x989BdC1DC4d116d30edc8Fd8D2465a0cD0E273b5

# Setup bridge adapter roles

=========================

pnpm hardhat setup-bridge-adapter --network 80001 --bridge-address 0xAF954C2fcdcf01B891eA267224E3781E9B0Ed9AC --adapter-address 0x66d51e543a7C58a83dE2924bcc6Eca83866C3A7d --adapter-router-address 0x70499c328e1e2a3c41108bd3730f6670a44595d1 --router-to-adapter-function-selector ccipReceive ----bridge-to-adapter-function-selector sendMessageUsingERC20 --adapter-contract-name CCIPAdapter
pnpm hardhat setup-bridge-adapter --network 80001 --bridge-address 0x7afB1dC8685AEf673119D717109b631eb8116d42 --adapter-address 0xb49eBCDB0081baD196e7Bff41fA1614149Ce6eEB --adapter-router-address 0x70499c328e1e2a3c41108bd3730f6670a44595d1 --router-to-adapter-function-selector ccipReceive ----bridge-to-adapter-function-selector sendMessageUsingERC20 --adapter-contract-name CCIPAdapter

# Bridge ERC721 using ERC20 token as fee
# Verify

=========================

pnpm hardhat bridge-erc721-using-erc20 --network 80001 --token-name "hello" --token-symbol "world" --bridge-address 0x89d50fBE79D31CBF1d9661f411C7865b611AC6f9 --adapter-address 0xaE784bC30BC8D29f9493a4366137bF371775159f --target-network 43113 --fee-token-name LINK
pnpm hardhat verify --network 80001 --contract contracts/adapters/CCIPAdapter.sol:CCIPAdapter 0x45ACa774719B311fF4DA05724866DdBC18f3e31c 0xAC4c62F5aeBfc879AeB4A3b919be608980E73D56 0xBbd6d4dC3BF45fdbc286a01916eb7611b727957c 0x70499c328e1e2a3c41108bd3730f6670a44595d1 0x326C977E6efc84E512bB9C30f76E30c160eD06FB

pnpm hardhat verify --network 80001 --contract contracts/Bridge.sol:Bridge 0xAC4c62F5aeBfc879AeB4A3b919be608980E73D56 0xBbd6d4dC3BF45fdbc286a01916eb7611b727957c 80001
23 changes: 18 additions & 5 deletions contracts-right.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,34 @@ pnpm hardhat deploy-bridge-contract --network 43113

=========================

pnpm hardhat deploy-adapter-contract --network 43113 --adapter "CCIPAdapter" --bridge-address 0x7b9Dbf30BB2144b22f612B2bf7f02cb9dB36Bca1 --router-address 0x554472a2720e5e7d5d3c817529aba05eed5f82d8 --fee-token-name LINK
pnpm hardhat deploy-adapter-contract --network 43113 --adapter "CCIPAdapter" --bridge-address 0x0214f538B87996Dc42924DCeeb84023D01C50dFC --router-address 0x554472a2720e5e7d5d3c817529aba05eed5f82d8 --fee-token-name LINK

# Set chain settings

=========================

pnpm hardhat set-chain-settings --network 43113 --bridge-address 0x7b9Dbf30BB2144b22f612B2bf7f02cb9dB36Bca1 --evm-chain-id 80001 --non-evm-chain-id 12532609583862916517 --adapter-address 0x940D6921A7931AFB07107323118F2151DCBCF2eC ---target-adapter-address 0xaE784bC30BC8D29f9493a4366137bF371775159f --is-enabled true --gas-limit 4000000
pnpm hardhat set-chain-settings --network 43113 --bridge-address 0x0214f538B87996Dc42924DCeeb84023D01C50dFC --evm-chain-id 80001 --non-evm-chain-id 0x01Dfab90DC8C8E5F66E3fB51009B4c5D8820e44f12532609583862916517 --adapter-address 0x01Dfab90DC8C8E5F66E3fB51009B4c5D8820e44f ---target-adapter-address 0x45ACa774719B311fF4DA05724866DdBC18f3e31c --is-enabled true --gas-limit 4000000

# Bridge ERC721 using ERC20 token as fee

=========================
pnpm hardhat bridge-erc721-using-erc20 --network 43113 --token-name "hello" --token-symbol "world" --bridge-address 0x0214f538B87996Dc42924DCeeb84023D01C50dFC --adapter-address 0x01Dfab90DC8C8E5F66E3fB51009B4c5D8820e44f --target-network 80001 --fee-token-name LINK

# Execute

==========================
pnpm hardhat execute-message --network 43113 --adapter-address 0x7f188288e39197B7e55EC4E08a9f19f56A8580e8

# Setup bridge adapter roles

================s=========
==========================

pnpm hardhat setup-bridge-adapter --network 43113 --bridge-address 0xFB6F96b38AEaA0489FC0eEee8B105484f2111d99 --adapter-address 0xFaA94F0D45e70dc672A796Eafb6E21475a62Db9C --adapter-router-address 0x966A8C1a84D02a4BF95936386983bCaAfbF1EB52 --router-to-adapter-function-selector ccipReceive ----bridge-to-adapter-function-selector sendMessageUsingERC20 --adapter-contract-name CCIPAdapter

# Bridge ERC721 using ERC20 token as fee
# Verify

=========================
pnpm hardhat bridge-erc721-using-erc20 --network 43113 --token-name "hello" --token-symbol "world" --bridge-address 0x7b9Dbf30BB2144b22f612B2bf7f02cb9dB36Bca1 --adapter-address 0x940D6921A7931AFB07107323118F2151DCBCF2eC --target-network 80001 --fee-token-name LINK

pnpm hardhat verify --network 43113 --contract contracts/adapters/CCIPAdapter.sol:CCIPAdapter 0x01Dfab90DC8C8E5F66E3fB51009B4c5D8820e44f 0x0214f538B87996Dc42924DCeeb84023D01C50dFC 0x554472a2720e5e7d5d3c817529aba05eed5f82d8 0x7953C478A5F5d53C263Bd1251BfC4c418d8C5568 0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846

pnpm hardhat verify --network 43113 --contract contracts/Bridge.sol:Bridge 0x0214f538B87996Dc42924DCeeb84023D01C50dFC 0x7953C478A5F5d53C263Bd1251BfC4c418d8C5568 43113
60 changes: 39 additions & 21 deletions contracts/Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {IBridge} from "./interfaces/IBridge.sol";
import {IERC721, IERC721Metadata, IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {WERC721} from "./wrapped/WERC721.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "hardhat/console.sol";

contract Bridge is IBridge, AccessManaged {
uint256 private immutable s_chainId;
Expand All @@ -28,13 +27,20 @@ contract Bridge is IBridge, AccessManaged {
s_chainId = chainId_;
}

modifier checkEvmChainIdAdapterIsValid(IBridge.EvmChainSettings memory evmChainSettings_) {
modifier checkEvmChainIdAdapterOnRamp(IBridge.EvmChainSettings memory evmChainSettings_) {
if (evmChainSettings_.adapter == address(0)) {
revert IBridge.AdapterNotFound();
}
_;
}

modifier checkEvmChainIdAdapterOffRamp(IBridge.EvmChainSettings memory evmChainSettings_, address sender_) {
if (evmChainSettings_.adapter != sender_) {
revert IBridge.AdapterNotFound();
}
_;
}

modifier checkEvmChainIdIsEnabled(IBridge.EvmChainSettings memory evmChainSettings_) {
if (!evmChainSettings_.isEnabled) {
revert IBridge.AdapterNotEnabled();
Expand Down Expand Up @@ -103,6 +109,12 @@ contract Bridge is IBridge, AccessManaged {
emit IBridge.ERC721WrappedCreated(originEvmChainId_, originAddress_, wrappedAddress_);
}

function getERC721WrappedToken(address originAddress_) external view returns (IBridge.ERC721Wrapped memory) {
return s_wrappedERC721Tokens[originAddress_];
}

/// @dev todo: reentracy guard

/// @inheritdoc IBridge
function sendERC721UsingERC20(
uint256 toChain_,
Expand All @@ -111,21 +123,21 @@ contract Bridge is IBridge, AccessManaged {
uint256 amount_
)
external
checkEvmChainIdAdapterIsValid(getChainSettings(toChain_, IBridge.RampType.OnRamp))
checkEvmChainIdAdapterOnRamp(getChainSettings(toChain_, IBridge.RampType.OnRamp))
checkEvmChainIdIsEnabled(getChainSettings(toChain_, IBridge.RampType.OnRamp))
{
IBaseAdapter adapter = IBaseAdapter(getChainSettings(toChain_, IBridge.RampType.OnRamp).adapter);

address feeToken = adapter.feeToken();
if (feeToken == address(0)) revert IBridge.OperationNotSupported();

IBridge.ERC721Send memory payload = _getPayload(toChain_, token_, tokenId_);
IBaseAdapter.MessageSend memory payload = _getPayload(toChain_, token_, tokenId_);
if (adapter.getFee(payload) > amount_) revert IBridge.InsufficientFeeTokenAmount();

/// @dev get fees tokens first
IERC20(feeToken).transferFrom(msg.sender, address(this), amount_);

_lockERC721FromSender(token_, tokenId_);
_receiveERC721FromSender(token_, tokenId_);

/// @dev approve adapter to spend fees tokens
IERC20(feeToken).approve(address(adapter), amount_);
Expand All @@ -135,15 +147,17 @@ contract Bridge is IBridge, AccessManaged {
emit IBridge.ERC721Sent(toChain_, payload.receiver, payload.data);
}

function _lockERC721FromSender(address token_, uint256 tokenId_) private {
function _receiveERC721FromSender(address token_, uint256 tokenId_) private {
/// @dev check if its wrapped, then burn instead of transfer
address existentWrappedAddress = s_wrappedERC721Tokens[s_wrappedERC721TokenOrigin[token_]].wrappedAddress;

if (existentWrappedAddress != address(0)) {
WERC721 wERC721 = WERC721(existentWrappedAddress);
wERC721.safeTransferFrom(msg.sender, address(this), tokenId_);
/// @dev burn wrapped token before sending back
wERC721.bridgeBurn(tokenId_);
} else {
/// @dev just lock original ERC721
IERC721(token_).safeTransferFrom(msg.sender, address(this), tokenId_);
}
}
Expand All @@ -156,16 +170,16 @@ contract Bridge is IBridge, AccessManaged {
)
external
payable
checkEvmChainIdAdapterIsValid(getChainSettings(toChain_, IBridge.RampType.OnRamp))
checkEvmChainIdAdapterOnRamp(getChainSettings(toChain_, IBridge.RampType.OnRamp))
checkEvmChainIdIsEnabled(getChainSettings(toChain_, IBridge.RampType.OnRamp))
{
IBaseAdapter adapter = IBaseAdapter(getChainSettings(toChain_, IBridge.RampType.OnRamp).adapter);
if (adapter.feeToken() != address(0)) revert IBridge.OperationNotSupported();

IBridge.ERC721Send memory payload = _getPayload(toChain_, token_, tokenId_);
IBaseAdapter.MessageSend memory payload = _getPayload(toChain_, token_, tokenId_);
if (adapter.getFee(payload) > msg.value) revert IBridge.InsufficientFeeTokenAmount();

_lockERC721FromSender(token_, tokenId_);
_receiveERC721FromSender(token_, tokenId_);

adapter.sendMessageUsingNative{value: msg.value}(payload);

Expand All @@ -176,19 +190,19 @@ contract Bridge is IBridge, AccessManaged {
uint256 evmChainId_,
address token_,
uint256 tokenId_
) internal view returns (IBridge.ERC721Send memory) {
) internal view returns (IBaseAdapter.MessageSend memory) {
/// @dev get target details to prepare payload
EvmChainSettings memory offRampChainSettings = getChainSettings(evmChainId_, IBridge.RampType.OffRamp);
IERC721Metadata metadata = IERC721Metadata(token_);

return
IBridge.ERC721Send({
IBaseAdapter.MessageSend({
gasLimit: offRampChainSettings.gasLimit,
toChain: offRampChainSettings.nonEvmChainId, /// @dev adapter use nonvEvmChainId to handle message
receiver: offRampChainSettings.adapter, /// @dev adatper address that will receive the message
data: _getEncodedPayloadData(
msg.sender, /// @dev address that will receive the ERC721 wrapped in the other chain
abi.encode(evmChainId_, token_, tokenId_),
abi.encode(s_chainId, token_, tokenId_),
abi.encode(metadata.name(), metadata.symbol(), metadata.tokenURI(tokenId_))
)
});
Expand All @@ -202,29 +216,33 @@ contract Bridge is IBridge, AccessManaged {
return abi.encode(receiver_, token_, metadata_);
}

/// @dev todo: split this operation to handle by automation instead using a setup like executeByAutomation = true
/// @inheritdoc IBridge
function receiveERC721(
IBridge.ERC721Receive memory payload_
IBaseAdapter.MessageReceive memory payload_
)
external
override
restricted
checkEvmChainIdAdapterIsValid(getChainSettings(s_nonEvmChains[payload_.fromChain], IBridge.RampType.OffRamp))
checkEvmChainIdAdapterOffRamp(
getChainSettings(s_nonEvmChains[payload_.fromChain], IBridge.RampType.OffRamp),
payload_.sender
)
checkEvmChainIdIsEnabled(getChainSettings(s_nonEvmChains[payload_.fromChain], IBridge.RampType.OffRamp))
{
uint256 evmChainId = s_nonEvmChains[payload_.fromChain];
uint256 fromEvmChainId = s_nonEvmChains[payload_.fromChain];

IBridge.ERC721Data memory data = _getDecodedERC721Data(payload_.data);
IBridge.ERC721Token memory token = _getDecodedERC721Token(data.token);

address wrappedERC721Token;
address originTokenAddress = token.tokenAddress;
address receiver = data.receiver;
uint256 tokenId = token.tokenId;

if (token.evmChainId == s_chainId) {
/// @dev unlock and transfer to receiver
wrappedERC721Token = originTokenAddress;
IERC721(wrappedERC721Token).safeTransferFrom(address(this), data.receiver, token.tokenId);
IERC721(wrappedERC721Token).transferFrom(address(this), receiver, tokenId);
} else {
IBridge.ERC721Metadata memory metadata = _getDecodedERC721Metadata(data.metadata);
address wrappedERC721Token_ = s_wrappedERC721Tokens[originTokenAddress].wrappedAddress;
Expand All @@ -237,10 +255,10 @@ contract Bridge is IBridge, AccessManaged {
wrappedERC721Token = wrappedERC721Token_;
}

WERC721(wrappedERC721Token).bridgeMint(data.receiver, token.tokenId, metadata.tokenURI);
WERC721(wrappedERC721Token).bridgeMint(receiver, tokenId, metadata.tokenURI);
}

emit IBridge.ERC721Received(evmChainId, data.receiver, payload_.data);
emit IBridge.ERC721Received(fromEvmChainId, receiver, payload_.data);
}

function _getDecodedERC721Data(bytes memory data_) internal pure returns (IBridge.ERC721Data memory) {
Expand All @@ -263,7 +281,7 @@ contract Bridge is IBridge, AccessManaged {
}

function _createWrapped(
IBridge.ERC721Receive memory payload_,
IBaseAdapter.MessageReceive memory payload_,
address token,
string memory name_,
string memory symbol_
Expand All @@ -275,7 +293,7 @@ contract Bridge is IBridge, AccessManaged {
assembly {
wrappedERC721Token := create2(0, add(bytecode, 0x20), mload(bytecode), salt)

if iszero(extcodesize(token)) {
if iszero(extcodesize(wrappedERC721Token)) {
revert(0, 0)
}
}
Expand Down
21 changes: 9 additions & 12 deletions contracts/adapters/BaseAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ abstract contract BaseAdapter is IBaseAdapter, AccessManaged {
}

/// @inheritdoc IBaseAdapter
function bridge() public view override returns (address) {
function getBridge() public view override returns (address) {
return s_bridge;
}

/// @inheritdoc IBaseAdapter
function getFee(IBridge.ERC721Send memory payload_) public view virtual override returns (uint256);
function getFee(IBaseAdapter.MessageSend memory payload_) public view virtual override returns (uint256);

/// @inheritdoc IBaseAdapter
function feeToken() public view virtual override returns (address) {
Expand All @@ -30,31 +30,28 @@ abstract contract BaseAdapter is IBaseAdapter, AccessManaged {

/// @inheritdoc IBaseAdapter
function sendMessageUsingERC20(
IBridge.ERC721Send memory payload_,
IBaseAdapter.MessageSend memory payload_,
uint256 quotedFee_
) external override restricted {
/// @dev check if there is enough fee token amount
if (quotedFee_ < getFee(payload_)) revert InsufficientFeeTokenAmount();

_sendMessage(payload_, quotedFee_);
emit IBaseAdapter.ERC721Sent(payload_.toChain, payload_.receiver, payload_.data);
emit IBaseAdapter.MessageSent(payload_.toChain, payload_.receiver, payload_.data);
}

/// @inheritdoc IBaseAdapter
function sendMessageUsingNative(IBridge.ERC721Send memory payload_) external payable override restricted {
/// @dev check if there is enough fee token amount
function sendMessageUsingNative(IBaseAdapter.MessageSend memory payload_) external payable override restricted {
if (msg.value < getFee(payload_)) revert InsufficientFeeTokenAmount();

_sendMessage(payload_, msg.value);
emit IBaseAdapter.ERC721Sent(payload_.toChain, payload_.receiver, payload_.data);
emit IBaseAdapter.MessageSent(payload_.toChain, payload_.receiver, payload_.data);
}

///@dev {override} this function to send message using your implementation
function _sendMessage(IBridge.ERC721Send memory payload_, uint256 quotedFee_) internal virtual;
function _sendMessage(IBaseAdapter.MessageSend memory payload_, uint256 quotedFee_) internal virtual;

function _receiveMessage(IBridge.ERC721Receive memory payload_) internal virtual {
function _receiveMessage(IBaseAdapter.MessageReceive memory payload_) internal virtual {
IBridge(s_bridge).receiveERC721(payload_);
emit IBaseAdapter.ERC721Received(payload_.fromChain, payload_.sender, payload_.data);
emit IBaseAdapter.MessageReceived(payload_.fromChain, payload_.sender, payload_.data);
}

/// @dev prevent to receive native token
Expand Down
Loading

0 comments on commit 55ded95

Please sign in to comment.