Skip to content

Commit

Permalink
fix: transfer issues
Browse files Browse the repository at this point in the history
  • Loading branch information
wellitongervickas committed Nov 20, 2023
1 parent 4f0ba80 commit 6384584
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 56 deletions.
34 changes: 17 additions & 17 deletions contracts/Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ pragma solidity 0.8.21;
import {AccessManaged} from "@openzeppelin/contracts/access/manager/AccessManaged.sol";
import {IBaseAdapter} from "./interfaces/IBaseAdapter.sol";
import {IBridge} from "./interfaces/IBridge.sol";
import {IERC721, IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {ERC721, IERC721, IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";

contract Bridge is IBridge, AccessManaged {
/// @dev nativeChainId => adapterChainId => adapter
/// @dev nativeChainId => chainId => adapter
mapping(uint256 => IBridge.AdapterSettings) public s_adapters;

constructor(address accessManagement_) AccessManaged(accessManagement_) {}
Expand All @@ -20,10 +20,10 @@ contract Bridge is IBridge, AccessManaged {
}

/// @inheritdoc IBridge
function setAdapter(uint256 nativeChainId_, uint256 adapterChainId_, address adapter_) external restricted {
s_adapters[nativeChainId_] = IBridge.AdapterSettings({adapterChainId: adapterChainId_, adapter: adapter_});
function setAdapter(uint256 nativeChainId_, uint256 chainId_, address adapter_) external restricted {
s_adapters[nativeChainId_] = IBridge.AdapterSettings({chainId: chainId_, adapter: adapter_});

emit IBridge.AdapterSet(nativeChainId_, adapterChainId_, adapter_);
emit IBridge.AdapterSet(nativeChainId_, chainId_, adapter_);
}

/// @inheritdoc IBridge
Expand All @@ -32,32 +32,32 @@ contract Bridge is IBridge, AccessManaged {
}

/// @inheritdoc IBridge
function transferToChain(
function transferERC721(
uint256 toChain_,
address receiver_,
address token_,
uint256 tokenId_
) external payable checkAdapter(toChain_) {
AdapterSettings memory chainAdapter = adapters(toChain_);
address adapter = chainAdapter.adapter;

/// todo: encode baseURI and other data aswell
bytes memory data = abi.encode(token_, tokenId_);
IBaseAdapter adapter = IBaseAdapter(chainAdapter.adapter);

IBridge.MessageSend memory payload = IBridge.MessageSend({
toChain: chainAdapter.adapterChainId,
receiver: receiver_,
data: data
});
uint256 chainId = chainAdapter.chainId;

uint256 quotedFees = IBaseAdapter(adapter).getFee(payload);
ERC721 token = ERC721(token_);

bytes memory data = abi.encode(token_, tokenId_, token.name(), token.symbol(), token.tokenURI(tokenId_));

IBridge.MessageSend memory payload = IBridge.MessageSend({toChain: chainId, receiver: receiver_, data: data});

uint256 quotedFees = adapter.getFee(payload);
if (quotedFees > msg.value) {
revert IBridge.InsufficientFeeTokenAmount();
}

IERC721(token_).safeTransferFrom(msg.sender, address(this), tokenId_);

IBaseAdapter(adapter).sendMessage(payload);
adapter.sendMessage(payload);

emit IBridge.MessageSent(payload.toChain, payload.receiver, payload.data);
}
Expand All @@ -67,7 +67,7 @@ contract Bridge is IBridge, AccessManaged {
/// todo: set wrapped asset or create wrapped on lock
/// @inheritdoc IBridge
/// @dev only adapter can call
function receiveFromChain(IBridge.MessageReceive memory payload_) external override restricted {
function commitOffRamp(IBridge.MessageReceive memory payload_) external override restricted {
emit IBridge.MessageReceived(payload_.fromChain, payload_.sender, payload_.data);
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/adapters/BaseAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ abstract contract BaseAdapter is IBaseAdapter, AccessManaged {
* @param payload_ data to send to bridge
*/
function _receiveMessage(IBridge.MessageReceive memory payload_) internal virtual {
IBridge(s_bridge).receiveFromChain(payload_);
IBridge(s_bridge).commitOffRamp(payload_);
emit IBaseAdapter.MessageReceived(payload_.fromChain, payload_.sender, payload_.data);
}

Expand Down
12 changes: 6 additions & 6 deletions contracts/interfaces/IBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity 0.8.21;

interface IBridge {
struct AdapterSettings {
uint256 adapterChainId;
uint256 chainId;
address adapter;
}

Expand All @@ -29,7 +29,7 @@ interface IBridge {
error AdapterNotFound(uint256 nativeChainId_);

/// @dev Emitted when adapter is changed
event AdapterSet(uint256 indexed nativeChainId_, uint256 indexed adapterChainId_, address adapter_);
event AdapterSet(uint256 indexed nativeChainId_, uint256 indexed chainId_, address adapter_);

/// @dev Emitted when message is sent
event MessageSent(uint256 toChain, address receiver, bytes data);
Expand All @@ -40,10 +40,10 @@ interface IBridge {
/**
* @notice set adapter address from native chainId and abstracted chainId
* @param nativeChainId_ native chain id
* @param adapterChainId_ abstracted chain id
* @param chainId_ abstracted chain id
* @param adapter_ address of adapter
*/
function setAdapter(uint256 nativeChainId_, uint256 adapterChainId_, address adapter_) external;
function setAdapter(uint256 nativeChainId_, uint256 chainId_, address adapter_) external;

/**
* @notice get adapter address by native chainId
Expand All @@ -59,7 +59,7 @@ interface IBridge {
* @param token_ token address of collection
* @param tokenId_ token id to transfer
*/
function transferToChain(uint256 toChain_, address receiver_, address token_, uint256 tokenId_) external payable;
function transferERC721(uint256 toChain_, address receiver_, address token_, uint256 tokenId_) external payable;

/**
* @notice receive NFT transfers
Expand All @@ -71,5 +71,5 @@ interface IBridge {
* @notice receive message from adapter
* @param payload_ data received from adapter
*/
function receiveFromChain(IBridge.MessageReceive memory payload_) external;
function commitOffRamp(IBridge.MessageReceive memory payload_) external;
}
2 changes: 1 addition & 1 deletion contracts/mocks/MockBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ contract MockBridge {

event MessageReceived(MessageReceive indexed message_);

function receiveFromChain(MessageReceive memory calldata_) external {
function commitOffRamp(MessageReceive memory calldata_) external {
emit MessageReceived(calldata_);
}
}
67 changes: 36 additions & 31 deletions test/bridge/Bridge.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,10 @@ describe('Bridge', function () {
)

const nativeChainId = 137
const adapterChainId = 80_001
const chainId = 80_001

await expect(
bridge
.connect(unknown)
.setAdapter(nativeChainId, adapterChainId, adapterAddress)
bridge.connect(unknown).setAdapter(nativeChainId, chainId, adapterAddress)
).to.be.revertedWithCustomError(bridge, 'AccessManagedUnauthorized')
})

Expand All @@ -50,14 +48,14 @@ describe('Bridge', function () {
)

const nativeChainId = 137
const adapterChainId = 80_001
const chainId = 80_001

await bridge.setAdapter(nativeChainId, adapterChainId, adapterAddress)
await bridge.setAdapter(nativeChainId, chainId, adapterAddress)

const adapter = await bridge.adapters(nativeChainId)

expect([adapter.adapterChainId, adapter.adapter]).to.deep.equal([
adapterChainId,
expect([adapter.chainId, adapter.adapter]).to.deep.equal([
chainId,
adapterAddress
])
})
Expand All @@ -70,13 +68,11 @@ describe('Bridge', function () {
)

const nativeChainId = 137
const adapterChainId = 80_001
const chainId = 80_001

await expect(
bridge.setAdapter(nativeChainId, adapterChainId, adapterAddress)
)
await expect(bridge.setAdapter(nativeChainId, chainId, adapterAddress))
.to.emit(bridge, 'AdapterSet')
.withArgs(nativeChainId, adapterChainId, adapterAddress)
.withArgs(nativeChainId, chainId, adapterAddress)
})

it('should revert if chain does not have any adapter', async function () {
Expand All @@ -90,7 +86,7 @@ describe('Bridge', function () {
const nativeChainId = 137

await expect(
bridge.transferToChain(
bridge.transferERC721(
nativeChainId,
receiver.address,
fakeNFTAddress,
Expand All @@ -100,32 +96,34 @@ describe('Bridge', function () {
})

it('should revert if the amount sent as fee token is insufficient', async function () {
const fakeNFTAddress = ethers.ZeroAddress
const fakeNFTTokenId = 0
const { mockNFTAddress, mockNFT } = await loadFixture(deployMockNFTFixture)

const [receiver] = await getSigners()

const { bridge } = await loadFixture(
const { bridge, bridgeAddress } = await loadFixture(
deployBridgeFixture.bind(this, accessManagementAddress)
)

const nativeChainId = 137
const adapterChainId = 12334124515
const chainId = 12334124515

const { mockAdapterAddress, mockAdapter } = await loadFixture(
deployMockAdapterFixture
)

await mockAdapter.setFee(200_000)
await bridge.setAdapter(nativeChainId, chainId, mockAdapterAddress)

await bridge.setAdapter(nativeChainId, adapterChainId, mockAdapterAddress)
const tokenId = 1
await mockNFT.mint(tokenId)
await mockNFT.approve(bridgeAddress, tokenId)

await expect(
bridge.transferToChain(
bridge.transferERC721(
nativeChainId,
receiver.address,
fakeNFTAddress,
fakeNFTTokenId
mockNFTAddress,
tokenId
)
).to.be.revertedWithCustomError(bridge, 'InsufficientFeeTokenAmount')
})
Expand All @@ -140,17 +138,17 @@ describe('Bridge', function () {
)

const nativeChainId = 137
const adapterChainId = 12334124515
const chainId = 12334124515

const { mockAdapterAddress } = await loadFixture(deployMockAdapterFixture)

await bridge.setAdapter(nativeChainId, adapterChainId, mockAdapterAddress)
await bridge.setAdapter(nativeChainId, chainId, mockAdapterAddress)

const tokenId = 1
await mockNFT.mint(tokenId)
await mockNFT.approve(bridgeAddress, tokenId)

await bridge.transferToChain(
await bridge.transferERC721(
nativeChainId,
receiver.address,
mockNFTAddress,
Expand All @@ -171,31 +169,38 @@ describe('Bridge', function () {
)

const nativeChainId = 137
const adapterChainId = 12334124515
const chainId = 12334124515

const { mockAdapterAddress } = await loadFixture(deployMockAdapterFixture)

await bridge.setAdapter(nativeChainId, adapterChainId, mockAdapterAddress)
await bridge.setAdapter(nativeChainId, chainId, mockAdapterAddress)

const tokenId = 1
await mockNFT.mint(tokenId)
await mockNFT.approve(bridgeAddress, tokenId)

// , 'string', 'string', 'string'
const encodedData = abiCoder.encode(
['address', 'uint256'],
[mockNFTAddress, tokenId]
['address', 'uint256', 'string', 'string', 'string'],
[
mockNFTAddress,
tokenId,
await mockNFT.name(),
await mockNFT.symbol(),
await mockNFT.tokenURI(tokenId)
]
)

await expect(
bridge.transferToChain(
bridge.transferERC721(
nativeChainId,
receiver.address,
mockNFTAddress,
tokenId
)
)
.to.emit(bridge, 'MessageSent')
.withArgs(adapterChainId, receiver.address, encodedData)
.withArgs(chainId, receiver.address, encodedData)
})

it('should revert if call safe transfer from another contract', async function () {
Expand Down

0 comments on commit 6384584

Please sign in to comment.