Skip to content

Commit

Permalink
feat: adding manuallly execute message
Browse files Browse the repository at this point in the history
  • Loading branch information
wellitongervickas committed Dec 4, 2023
1 parent 36d17c2 commit 8217efa
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 170 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
## Networks

- Avalanche Fuji (43113)
- Optimism Goerli (420)
- Mumbai (80001)
- Base goerli (84531)

## Getting Started

Expand Down
108 changes: 4 additions & 104 deletions config/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export const avalancheFuji: Chain = {
},
testnet: true,
crosschain: {
gasRequiredDeploy: 13201611n,
gasRequiredToMint: 68282n
gasRequiredDeploy: 1299614n,
gasRequiredToMint: 95639n
},
assets: {
LINK: {
Expand Down Expand Up @@ -87,8 +87,8 @@ export const polygonMumbai: Chain = {
},
testnet: true,
crosschain: {
gasRequiredDeploy: 74007900740079n,
gasRequiredToMint: 68282n
gasRequiredDeploy: 1300024n,
gasRequiredToMint: 95639n
},
assets: {
LINK: {
Expand All @@ -97,103 +97,3 @@ export const polygonMumbai: Chain = {
}
}
}

export const optimismGoerli: Chain = {
id: 420,
name: 'Optimism Goerli',
network: 'optimism-goerli',
nativeCurrency: { name: 'Goerli Ether', symbol: 'ETH', decimals: 18 },
accounts: evmAccounts,
rpcUrls: {
protocol: {
http: [process.env.PUBLIC_NETWORK_420_HTTP_RPC!]
},
default: {
http: ['https://goerli.optimism.io']
},
public: {
http: ['https://goerli.optimism.io']
}
},
blockExplorers: {
etherscan: {
name: 'Etherscan',
url: 'https://goerli-optimism.etherscan.io'
},
default: {
name: 'Etherscan',
url: 'https://goerli-optimism.etherscan.io'
}
},
contracts: {
multicall3: {
address: '0xca11bde05977b3631167028862be2a173976ca11',
blockCreated: 49461
},
accessManagement: {
address: '0x483E5D5a59EeB5dB9c2AAC502Da40fab173b8DF2',
blockCreated: 0
}
},
testnet: true,
crosschain: {
gasRequiredDeploy: 1206898n,
gasRequiredToMint: 68282n
},
assets: {
LINK: {
address: '0xdc2CC710e42857672E7907CF474a69B63B93089f',
decimals: 18
}
}
}

export const baseGoerli: Chain = {
id: 84531,
network: 'base-goerli',
name: 'Base Goerli',
accounts: evmAccounts,
nativeCurrency: { name: 'Goerli Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: {
protocol: {
http: [process.env.PUBLIC_NETWORK_84531_HTTP_RPC!]
},
default: {
http: ['https://goerli.base.org']
},
public: {
http: ['https://goerli.base.org']
}
},
blockExplorers: {
etherscan: {
name: 'Basescan',
url: 'https://goerli.basescan.org'
},
default: {
name: 'Basescan',
url: 'https://goerli.basescan.org'
}
},
contracts: {
multicall3: {
address: '0xca11bde05977b3631167028862be2a173976ca11',
blockCreated: 1376988
},
accessManagement: {
address: '0x9eDb3e9d394B924a2FE264C170049795F849479c',
blockCreated: 0
}
},
testnet: true,
crosschain: {
gasRequiredDeploy: 1206898n,
gasRequiredToMint: 68282n
},
assets: {
LINK: {
address: '0x6D0F8D488B669aa9BA2D0f0b7B75a88bf5051CD3',
decimals: 18
}
}
}
14 changes: 2 additions & 12 deletions config/config.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
import { reduce } from 'lodash'
import {
avalancheFuji,
optimismGoerli,
baseGoerli,
polygonMumbai
} from './chains'
import { avalancheFuji, polygonMumbai } from './chains'
import { Chain } from './types'

export const allowedChains = [
avalancheFuji,
optimismGoerli,
baseGoerli,
polygonMumbai
]
export const allowedChains = [avalancheFuji, polygonMumbai]

export const allowedChainsConfig = reduce(
allowedChains,
Expand Down
8 changes: 4 additions & 4 deletions contracts-left.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@ pnpm hardhat deploy-bridge-contract --network 80001

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

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

# Set chain settings

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

pnpm hardhat set-chain-settings --network 80001 --bridge-address 0x8Dfc565d2514b2727A1f94641C7bA8650F96cfF1 --evm-chain-id 43113 --non-evm-chain-id 14767482510784806043 --adapter-address 0x3C66f7dC50c6Cd38d90707fD66de6041f7B42518 ---target-adapter-address 0x5da3Ef4Cd1437C6b4cFE46b852248A25D605759F --is-enabled true --gas-limit 4000000
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

# Setup bridge adapter roles

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

pnpm hardhat setup-bridge-adapter --network 80001 --bridge-address 0x3d7593Ef9d71959b86720e728c1e7469eeDE2d8e --adapter-address 0xA30A80709b97BCc6aF48c570507238627Da85822 --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 0xAF954C2fcdcf01B891eA267224E3781E9B0Ed9AC --adapter-address 0x66d51e543a7C58a83dE2924bcc6Eca83866C3A7d --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

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

pnpm hardhat bridge-erc721-using-erc20 --network 80001 --token-name "hello" --token-symbol "world" --bridge-address 0x8Dfc565d2514b2727A1f94641C7bA8650F96cfF1 --adapter-address 0x3C66f7dC50c6Cd38d90707fD66de6041f7B42518 --target-network 43113 --fee-token-name LINK
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
8 changes: 4 additions & 4 deletions contracts-right.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@ pnpm hardhat deploy-bridge-contract --network 43113

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

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

# Set chain settings

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

pnpm hardhat set-chain-settings --network 43113 --bridge-address 0xb8e9F7292be5105bF31281b74105D48e5578255a --evm-chain-id 80001 --non-evm-chain-id 12532609583862916517 --adapter-address 0x5da3Ef4Cd1437C6b4cFE46b852248A25D605759F ---target-adapter-address 0x3C66f7dC50c6Cd38d90707fD66de6041f7B42518 --is-enabled true --gas-limit 40000000
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

# Setup bridge adapter roles

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

pnpm hardhat setup-bridge-adapter --network 43113 --bridge-address 0x1BcCE6f7CFFB9bdF23836cD7f59E11D99112022a --adapter-address 0xf56F1C3E2A908eD9BF56BEc2Cb1C290De8A2936E --adapter-router-address 0x966A8C1a84D02a4BF95936386983bCaAfbF1EB52 --router-to-adapter-function-selector ccipReceive ----bridge-to-adapter-function-selector sendMessageUsingERC20 --adapter-contract-name CCIPAdapter
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

=========================
pnpm hardhat bridge-erc721-using-erc20 --network 43113 --token-name "hello" --token-symbol "world" --bridge-address 0xb8e9F7292be5105bF31281b74105D48e5578255a --adapter-address 0x5da3Ef4Cd1437C6b4cFE46b852248A25D605759F --target-network 80001 --fee-token-name LINK
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
50 changes: 27 additions & 23 deletions contracts/Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ contract Bridge is IBridge, AccessManaged {
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_);
Expand All @@ -126,23 +125,27 @@ contract Bridge is IBridge, AccessManaged {
/// @dev get fees tokens first
IERC20(feeToken).transferFrom(msg.sender, address(this), amount_);

_lockERC721FromSender(token_, tokenId_);

/// @dev approve adapter to spend fees tokens
IERC20(feeToken).approve(address(adapter), amount_);

adapter.sendMessageUsingERC20(payload, amount_);

emit IBridge.ERC721Sent(toChain_, payload.receiver, payload.data);
}

function _lockERC721FromSender(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_);
wERC721.burn(tokenId_);
wERC721.bridgeBurn(tokenId_);
} else {
IERC721(token_).safeTransferFrom(msg.sender, address(this), tokenId_);
}

/// @dev approve adapter to spend fees tokens
IERC20(feeToken).approve(address(adapter), amount_);

adapter.sendMessageUsingERC20(payload, amount_);

emit IBridge.ERC721Sent(toChain_, payload.receiver, payload.data);
}

/// @inheritdoc IBridge
Expand All @@ -162,17 +165,7 @@ contract Bridge is IBridge, AccessManaged {
IBridge.ERC721Send memory payload = _getPayload(toChain_, token_, tokenId_);
if (adapter.getFee(payload) > msg.value) revert IBridge.InsufficientFeeTokenAmount();

/// @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_);
wERC721.burn(tokenId_);
} else {
/// @dev transfer to bridge contract to lock
IERC721(token_).safeTransferFrom(msg.sender, address(this), tokenId_);
}
_lockERC721FromSender(token_, tokenId_);

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

Expand Down Expand Up @@ -221,10 +214,11 @@ contract Bridge is IBridge, AccessManaged {
checkEvmChainIdIsEnabled(getChainSettings(s_nonEvmChains[payload_.fromChain], IBridge.RampType.OffRamp))
{
uint256 evmChainId = s_nonEvmChains[payload_.fromChain];
address wrappedERC721Token;

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

address wrappedERC721Token;
address originTokenAddress = token.tokenAddress;

if (token.evmChainId == s_chainId) {
Expand All @@ -243,8 +237,9 @@ contract Bridge is IBridge, AccessManaged {
wrappedERC721Token = wrappedERC721Token_;
}

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

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

Expand Down Expand Up @@ -273,8 +268,17 @@ contract Bridge is IBridge, AccessManaged {
string memory name_,
string memory symbol_
) private returns (address wrappedERC721Token) {
bytes memory constructorArgs = abi.encode(address(this), name_, symbol_);
bytes memory bytecode = abi.encodePacked(type(WERC721).creationCode, constructorArgs);
bytes32 salt = keccak256(abi.encodePacked(s_nonEvmChains[payload_.fromChain], token));
wrappedERC721Token = address(new WERC721{salt: salt}(address(this), name_, symbol_));

assembly {
wrappedERC721Token := create2(0, add(bytecode, 0x20), mload(bytecode), salt)

if iszero(extcodesize(token)) {
revert(0, 0)
}
}

_setERC721WrappedToken(wrappedERC721Token, s_nonEvmChains[payload_.fromChain], token);
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/adapters/BaseAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ abstract contract BaseAdapter is IBaseAdapter, AccessManaged {
emit IBaseAdapter.ERC721Sent(payload_.toChain, payload_.receiver, payload_.data);
}

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

function _receiveMessage(IBridge.ERC721Receive memory payload_) internal virtual {
Expand Down
44 changes: 43 additions & 1 deletion contracts/adapters/CCIPAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ import {IBridge} from "../interfaces/IBridge.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract CCIPAdapter is BaseAdapter, CCIPReceiver {
mapping(uint256 => IBridge.ERC721Receive) private s_pendingMessagesToExecute;
mapping(uint256 => IBridge.ERC721Receive) private s_pendingMessagesExecuted;

uint256 private s_pendingMessagesCount;
uint256 private s_pendingMessagesExecutedCount;

error NoMessagesAvailable();

constructor(
address bridge_,
address accessManagement_,
Expand Down Expand Up @@ -62,10 +70,44 @@ contract CCIPAdapter is BaseAdapter, CCIPReceiver {
data: any2EvmMessage.data
});

/// @dev todo: receive message but not execute, automate it
_receiveMessage(payload);
}

function _receiveMessage(IBridge.ERC721Receive memory payload_) internal virtual override {
try IBridge(bridge()).receiveERC721(payload_) {
/// @dev if success, just bypass
} catch {
_setPendingMessage(payload_);
}

emit IBaseAdapter.ERC721Received(payload_.fromChain, payload_.sender, payload_.data);
}

function _setPendingMessage(IBridge.ERC721Receive memory payload_) private {
s_pendingMessagesToExecute[s_pendingMessagesCount++] = payload_;
}

function manuallyExecuteMessages(uint256 limitToExecute_) public {
if (s_pendingMessagesCount == 0) revert NoMessagesAvailable();

for (uint256 i = 0; i < limitToExecute_; i++) {
IBridge.ERC721Receive memory payload = s_pendingMessagesToExecute[i];

_receiveMessage(payload);

s_pendingMessagesExecuted[s_pendingMessagesExecutedCount++] = payload;
s_pendingMessagesCount--;
}
}

function getPendingMessage(uint256 index_) public view returns (IBridge.ERC721Receive memory) {
return s_pendingMessagesToExecute[index_];
}

function getExecutedMessage(uint256 index_) public view returns (IBridge.ERC721Receive memory) {
return s_pendingMessagesExecuted[index_];
}

/// @inheritdoc BaseAdapter
function _sendMessage(IBridge.ERC721Send memory payload_, uint256 quotedFee_) internal override {
bool isFeeTokenNative = feeToken() == address(0);
Expand Down
Loading

0 comments on commit 8217efa

Please sign in to comment.