Skip to content

transfer native token to sourceTokenAddress #4

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

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
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
86 changes: 60 additions & 26 deletions contracts/app/Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

import "../DynamicMerkleTree.sol";

Expand All @@ -11,6 +12,7 @@ library BridgeLib {
address tokenAddress;
address destination;
uint256 amount;
uint256 fee;
uint256 startTime;
uint256 feeRampup;
}
Expand All @@ -33,17 +35,24 @@ contract BridgeSource {
constructor() {}

function withdraw(
address sourceTokenAddress,
BridgeLib.TransferData memory transferData,
bytes32[] memory proof
) public {
) public payable {
// safemath not needed for solidity 8
uint256 amountPlusFee = (transferData.amount *
(10000 + CONTRACT_FEE_BASIS_POINTS)) / 10000;
IERC20(transferData.tokenAddress).safeTransferFrom(
msg.sender,
address(this),
amountPlusFee
);

if (sourceTokenAddress == address(0)) {
require(msg.value >= amountPlusFee, "not enough msg.value");
payable(address(this)).transfer(amountPlusFee);
} else {
IERC20(sourceTokenAddress).safeTransferFrom(
msg.sender,
address(this),
amountPlusFee
);
}

BridgeLib.TransferInitiated memory transferInitiated = BridgeLib
.TransferInitiated({data: transferData, self: address(this)});
Expand All @@ -61,7 +70,7 @@ contract BridgeSource {
}
}

contract BridgeDestination {
contract BridgeDestination is ReentrancyGuard {
using SafeERC20 for IERC20;

struct TransferKey {
Expand Down Expand Up @@ -99,18 +108,32 @@ contract BridgeDestination {
view
returns (uint256)
{
// TODO:
return 0;
uint256 currentTime = block.timestamp;
if (currentTime < transferData.startTime) {
return 0;
} else if (
currentTime >= transferData.startTime + transferData.feeRampup
) {
return transferData.fee;
} else {
return transferData.fee * (currentTime - transferData.startTime);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return transferData.fee * (currentTime - transferData.startTime);
return transferData.fee * (currentTime - transferData.startTime) / transferData.feeRampup;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet fixed?

}
}

function buy(TransferKey memory tkey) public {
function buy(TransferKey memory tkey) public payable nonReentrant {
uint256 amount = tkey.transferData.amount - getLPFee(tkey.transferData);
// TODO: another token address on dest. chain?
IERC20(tkey.transferData.tokenAddress).safeTransferFrom(
msg.sender,
tkey.transferData.destination,
amount
);

if (tkey.transferData.tokenAddress == address(0)) {
require(msg.value >= amount, "not enough msg.value");
payable(tkey.transferData.destination).transfer(amount);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may need nonReentrant to avoid reentrancy attack?

} else {
// TODO: another token address on dest. chain?
IERC20(tkey.transferData.tokenAddress).safeTransferFrom(
msg.sender,
tkey.transferData.destination,
amount
);
}

bytes32 key = keccak256(abi.encode(tkey));
require(ownerMap[key] == address(0), "already bought or withdrawn");
Expand All @@ -124,7 +147,7 @@ contract BridgeDestination {
address sourceContract,
uint256 transferLen,
bytes32[] memory recordProof
) public {
) public nonReentrant {
if (!validatedStateRoots[stateRoot]) {
// TODO: prove stateRoot is in stateRootProof
validatedStateRoots[stateRoot] = true;
Expand All @@ -143,16 +166,27 @@ contract BridgeDestination {

bytes32 key = keccak256(abi.encode(tkey));
require(ownerMap[key] != address(2**160 - 1), "already withdrawn");
if (ownerMap[key] == address(0)) {
IERC20(tkey.transferData.tokenAddress).safeTransfer(
tkey.transferData.destination,
tkey.transferData.amount
);

if (tkey.transferData.tokenAddress != address(0)) {
if (ownerMap[key] == address(0)) {
IERC20(tkey.transferData.tokenAddress).safeTransfer(
tkey.transferData.destination,
tkey.transferData.amount
);
} else {
IERC20(tkey.transferData.tokenAddress).safeTransfer(
ownerMap[key],
tkey.transferData.amount
);
}
} else {
IERC20(tkey.transferData.tokenAddress).safeTransfer(
ownerMap[key],
tkey.transferData.amount
);
if (ownerMap[key] == address(0)) {
payable(tkey.transferData.destination).transfer(
tkey.transferData.amount
);
} else {
payable(ownerMap[key]).transfer(tkey.transferData.amount);
}
}

ownerMap[key] = address(2**160 - 1); // -1, not used any more
Expand Down