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

[WIP] Adding polygon support #15

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions contracts/_abstract/BuddleBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ abstract contract BuddleBridge is IBuddleBridge, Ownable {
/**
* @inheritdoc IBuddleBridge
*/
// TODO: Move this to a common state contract because otherwise we'd need to call the
// same function on every bridge contract every time BuddleSrcX is added on any X chain.
function addBuddleBridge(
uint256 _chain,
address _contract
Expand Down
164 changes: 164 additions & 0 deletions contracts/polygon/BuddleBridgePolygon.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8.11;

import "../_abstract/BuddleBridge.sol";

import "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol";
import "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol";


/*
Goeril: "RootChainManager": "0x0d2ae21bf7e72f646ef8e1f2aa92edbd13588691",
Mumbai: "ChildChainManager": "0xb5505a6d998549090530911180f38aC5130101c6"
:

*/

/**
*
*
*/
contract BuddleBridgePolygon is BuddleBridge {
using SafeERC20 for IERC20;

uint256 constant public CHAIN = 80001; // Polygon mumbai

address public messenger;
address public stdBridge;

/**********************
* onlyOwner functions *
***********************/

/**
* Initialize the contract with state variables
*
* @param _version Contract version
* @param _messenger The address of the L1 Cross Domain Messenger Contract
* @param _stdBridge The address of the L1 Standard Token Bridge
*/
function initialize(
bytes32 _version,
address _messenger,
address _stdBridge
) external onlyOwner {
require(bytes32(VERSION) == bytes32(""), "Contract already initialized!");

VERSION = _version;
messenger = _messenger;
stdBridge = _stdBridge;

buddleBridge[CHAIN] = address(this);
knownBridges[address(this)] = true;
}

function updateXDomainMessenger(
address _newMessengerAddress
) external onlyOwner checkInitialization {
messenger = _newMessengerAddress;
}

function updateStandardBridge(
address _newBridgeAddress
) external onlyOwner checkInitialization {
stdBridge = _newBridgeAddress;
}

/**********************
* public functions *
***********************/

/**
* @inheritdoc IBuddleBridge
*/
function claimBounty(
bytes32 _ticket,
uint _chain,
address[] memory _tokens,
uint256[] memory _amounts,
uint256[] memory _bounty,
uint256 _firstIdForTicket,
uint256 _lastIdForTicket,
bytes32 stateRoot
) external payable
checkInitialization {

ICrossDomainMessenger(messenger).sendMessage(
buddle.source,
abi.encodeWithSignature(
"confirmTicket(bytes32,uint256,address[],uint256[],uint256[],uint256,uint256,bytes32,address)",
_ticket, _chain, _tokens, _amounts, _bounty, _firstIdForTicket, _lastIdForTicket, stateRoot, msg.sender
),
1000000
);

IBuddleBridge _bridge = IBuddleBridge(buddleBridge[_chain]);
_bridge.transferFunds{value: msg.value}(_tokens, _amounts, msg.sender, _ticket);
_bridge.approveRoot(stateRoot);

}

/**
* @inheritdoc IBuddleBridge
*/
function transferFunds(
address[] memory _tokens,
uint256[] memory _amounts,
address bountySeeker,
bytes32 _ticket
) external payable
checkInitialization
onlyKnownBridge {

IL1StandardBridge _bridge = IL1StandardBridge(stdBridge);

for(uint i=0; i < _tokens.length; i++) {
if(_tokens[i] == BASE_TOKEN_ADDRESS) {
require(msg.value >= _amounts[i], "Insufficient funds sent");
_bridge.depositETHTo{value: msg.value}(
buddle.destination,
1000000,
bytes("")
);
} else {
IERC20 token = IERC20(_tokens[i]);
require(token.balanceOf(bountySeeker) >= _amounts[i], "Insufficient funds sent");

token.safeTransferFrom(bountySeeker, address(this), _amounts[i]);
token.approve(messenger, _amounts[i]);

_bridge.depositERC20To(
tokenMap[_tokens[i]], // L1 token address
_tokens[i], // L2 token address
buddle.destination, // to address
_amounts[i], // amount to be transferred
1000000, // Gas limit
bytes("") // Data empty
);
}
}

emit FundsBridged(CHAIN, _tokens, _amounts, block.timestamp, _ticket);

}

/**
* @inheritdoc IBuddleBridge
*/
function approveRoot(
bytes32 _root
) external
checkInitialization
onlyKnownBridge {

ICrossDomainMessenger(messenger).sendMessage(
buddle.destination,
abi.encodeWithSignature(
"approveStateRoot(uint256,bytes32)",
CHAIN, _root
),
1000000
);

}
}
49 changes: 49 additions & 0 deletions contracts/polygon/BuddleDestPolygon.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8.11;

import "../_abstract/BuddleDestination.sol";

import "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol";

contract BuddleDestPolygon is BuddleDestination {

address public messenger;

/**********************
* onlyOwner functions *
***********************/

/**
* Change the layer-2 cross domain messenger
*
* @param _messenger Layer-2 Cross Domain messenger contract
*/
function setXDomainMessenger(
address _messenger
) external onlyOwner checkInitialization {
messenger = _messenger;
}

/**
* Change the layer-2 cross domain messenger
*
* @param _newMessenger Layer-2 Cross Domain messenger contract
*/
function updateXDomainMessenger(
address _newMessenger
) external onlyOwner checkInitialization {
messenger = _newMessenger;
}

/**********************
* internal functions *
***********************/

/**
* @inheritdoc BuddleDestination
*/
function isBridgeContract() internal view override returns (bool) {
return (msg.sender == messenger &&
ICrossDomainMessenger(messenger).xDomainMessageSender() == buddleBridge);
}
}
86 changes: 86 additions & 0 deletions contracts/polygon/BuddleSrcPolygon.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8.11;

import "../_abstract/BuddleSource.sol";

import { FxStateChildTunnel } from "./FxStateChildTunnel.sol";
import { IFxMessageProcessor } from "./ext/FXBaseChildTunnel.sol";


/**
*
*
*/
contract BuddleSrcPolygon is BuddleSource {
using SafeERC20 for IERC20;

uint256 constant public CHAIN = 80001; // Polygon mumbai

IFxMessageProcessor public fxChildTunnel;

bool public isInitiated = false;

/**********************
* onlyOwner functions *
***********************/

/**
* Deploy new instance of FxStateChildTunnel and initialize contract
*
* @param _fxChild Polygon FxBaseChildTunnel address
*/
function setBuddleSrcPolygon(address _fxChild) external checkInitialization onlyOwner {
require(isInitiated == false, "Already initiated");
fxChildTunnel = new FxStateChildTunnel(_fxChild);
isInitiated = true;
}

function modifyFxStateChildTunnel(address _fxChild) external onlyOwner {
fxChildTunnel = _fxChild;
}


/**********************
* internal functions *
***********************/

/**
* @inheritdoc BuddleSource
*/
function isBridgeContract() internal view override returns (bool) {
return (msg.sender == address(fxChildTunnel));
}

/**
* @inheritdoc BuddleSource
*/
function _emitTransfer(
TransferData memory _data,
uint256 _id,
bytes32 _node
) internal override {
emit TransferStarted(_data, _id, _node, CHAIN);
}

/**
* @inheritdoc BuddleSource
*/
function _bridgeFunds(
uint256 _destChain,
address[] memory _tokens,
uint256[] memory _tokenAmounts,
uint256[] memory _bountyAmounts,
address _provider
) internal override {

for (uint n = 0; n < _tokens.length; n++) {
if(_tokens[n] == BASE_TOKEN_ADDRESS) {
address(0).transfer(_tokenAmounts[0]);
} else {
IERC20(_token[n]).transfer(address(0), _tokenAmounts[n]);
}
tokenAmounts[_destChain][_tokens[n]] -= _tokenAmounts[n];
bountyAmounts[_destChain][_tokens[n]] -= _bountyAmounts[n];
}
}
}
29 changes: 29 additions & 0 deletions contracts/polygon/FxStateChildTunnel.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { FxBaseChildTunnel } from "./ext/FxBaseChildTunnel.sol";

/**
* @title FxStateChildTunnel
*/
contract FxStateChildTunnel is FxBaseChildTunnel {
uint256 public latestStateId;
address public latestRootMessageSender;
( bytes public latestData;
)
constructor(address _fxChild) FxBaseChildTunnel(_fxChild) {}

function _processMessageFromRoot(
uint256 stateId,
address sender,
bytes memory data
) internal override validateSender(sender) {
latestStateId = stateId;
latestRootMessageSender = sender;
latestData = data;
}

function sendMessageToRoot(bytes memory message) public {
_sendMessageToRoot(message);
}
}
21 changes: 21 additions & 0 deletions contracts/polygon/FxStateRootTunnel.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {FxBaseRootTunnel} from "./ext/FxBaseRootTunnel.sol";

/**
* @title FxStateRootTunnel
*/
contract FxStateRootTunnel is FxBaseRootTunnel {
bytes public latestData;

constructor(address _checkpointManager, address _fxRoot) FxBaseRootTunnel(_checkpointManager, _fxRoot) {}

function _processMessageFromChild(bytes memory data) internal override {
latestData = data;
}

function sendMessageToChild(bytes memory message) public {
_sendMessageToChild(message);
}
}
Loading