-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge the develop branch to the master branch, preparation to v1.0.0-…
…rc2 (#13)
- Loading branch information
Showing
46 changed files
with
2,438 additions
and
891 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Omnibridge helpers contracts | ||
|
||
## WETHOmnibridgeRouter | ||
|
||
This contract allows reducing the number of actions required for native-to-erc20 bridging over Omnibridge. | ||
An example of such bridging scenarios might be: | ||
* Bridging ETH from Mainnet to the xDAI chain in a form of [WETH on xDAI](https://blockscout.com/poa/xdai/tokens/0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1/token-transfers) | ||
* Bridging BNB from BSC to the xDAI chain in a form of [WBNB on xDAI](https://blockscout.com/poa/xdai/tokens/0xCa8d20f3e0144a72C6B5d576e9Bd3Fd8557E2B04/token-transfers) | ||
|
||
Helper supports full-duplex bridging operations. | ||
Thus, there are 2 main usage scenarios for the helper contract. | ||
|
||
Even though the below examples are given for the BNB native coin from the BSC, | ||
the mechanism works exactly the same for other native coins as well. | ||
|
||
### BNB => WBNB => WBNB on xDAI | ||
|
||
In order to wrap native coins and bridge them through the Omnibridge to the other chain, make the following transaction: | ||
* Call `Helper.wrapAndRelayTokens()`/`Helper.wrapAndRelayTokens(receiver)` in BSC | ||
|
||
Desired bridged amount of BNB should be send as the transaction value argument. | ||
If the given amount of BNB cannot be bridged immediately, the whole transaction will revert. | ||
|
||
The upper call is identical to the following 3 sequential transactions: | ||
* Call `WBNB.deposit()` in BSC | ||
* Call `WBNB.approve(Omnibridge, value)` in BSC | ||
* Call `Omnibridge.relayTokens(WBNB, value)` in BSC | ||
|
||
### WBNB on xDAI => WBNB => BNB | ||
|
||
In order to bridged wrapped tokens back to the origin chain through the Omnibridge and automatically withdraw them, make the following transaction: | ||
* Call `WBNB_on_xDAI.transferAndCall(Omnibridge, value, Helper ++ receiver)` in xDAI | ||
|
||
Alternatively, make the following 2 transactions: | ||
* Call `WBNB_on_xDAI.approve(Omnibridge, value)` in xDAI | ||
* Call `Omnibridge.relayTokensAndCall(WBNB_on_xDAI, Helper, value, receiver)` in xDAI | ||
|
||
It is crucially important to correctly specify the receiver in the upper approaches. | ||
This should be an address of the final BNB receiver in BSC. | ||
Always include it explicitly in the call, even if msg.sender is equal to the receiver. | ||
|
||
The upper calls are identical to the following 3 sequential transactions: | ||
* Call `WBNB_on_xDAI.approve(Omnibridge, value)` in xDAI | ||
* Call `Omnibridge.relayTokens(WBNB_on_xDAI, value)` in xDAI | ||
* Call `WBNB.withdraw(value - fee)` in BSC |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
pragma solidity 0.7.5; | ||
|
||
import "../interfaces/IOmnibridge.sol"; | ||
import "../interfaces/IWETH.sol"; | ||
import "../libraries/AddressHelper.sol"; | ||
import "../upgradeable_contracts/modules/OwnableModule.sol"; | ||
import "../upgradeable_contracts/Claimable.sol"; | ||
|
||
/** | ||
* @title WETHOmnibridgeRouter | ||
* @dev Omnibridge extension for processing native and wrapped native assets. | ||
* Intended to work with WETH/WBNB/WXDAI tokens, see: | ||
* https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 | ||
* https://bscscan.com/address/0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c | ||
* https://blockscout.com/poa/xdai/address/0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d | ||
*/ | ||
contract WETHOmnibridgeRouter is OwnableModule, Claimable { | ||
IOmnibridge public immutable bridge; | ||
// solhint-disable-next-line var-name-mixedcase | ||
IWETH public immutable WETH; | ||
|
||
/** | ||
* @dev Initializes this contract. | ||
* @param _bridge address of the HomeOmnibridge/ForeignOmnibridge contract. | ||
* @param _weth address of the WETH token used for wrapping/unwrapping native coins (e.g. WETH/WBNB/WXDAI). | ||
* @param _owner address of the contract owner. | ||
*/ | ||
constructor( | ||
IOmnibridge _bridge, | ||
IWETH _weth, | ||
address _owner | ||
) OwnableModule(_owner) { | ||
bridge = _bridge; | ||
WETH = _weth; | ||
_weth.approve(address(_bridge), uint256(-1)); | ||
} | ||
|
||
/** | ||
* @dev Wraps native assets and relays wrapped ERC20 tokens to the other chain. | ||
* Call msg.sender will receive assets on the other side of the bridge. | ||
*/ | ||
function wrapAndRelayTokens() external payable { | ||
wrapAndRelayTokens(msg.sender); | ||
} | ||
|
||
/** | ||
* @dev Wraps native assets and relays wrapped ERC20 tokens to the other chain. | ||
* @param _receiver bridged assets receiver on the other side of the bridge. | ||
*/ | ||
function wrapAndRelayTokens(address _receiver) public payable { | ||
WETH.deposit{ value: msg.value }(); | ||
bridge.relayTokens(address(WETH), _receiver, msg.value); | ||
} | ||
|
||
/** | ||
* @dev Bridged callback function used for unwrapping received tokens. | ||
* Can only be called by the associated Omnibridge contract. | ||
* @param _token bridged token contract address, should be WETH. | ||
* @param _value amount of bridged/received tokens. | ||
* @param _data extra data passed alongside with relayTokensAndCall on the other side of the bridge. | ||
* Should contain coins receiver address. | ||
*/ | ||
function onTokenBridged( | ||
address _token, | ||
uint256 _value, | ||
bytes calldata _data | ||
) external { | ||
require(_token == address(WETH)); | ||
require(msg.sender == address(bridge)); | ||
require(_data.length == 20); | ||
|
||
WETH.withdraw(_value); | ||
|
||
address payable receiver; | ||
assembly { | ||
receiver := calldataload(120) | ||
} | ||
AddressHelper.safeSendValue(receiver, _value); | ||
} | ||
|
||
/** | ||
* @dev Claims stuck coins/tokens. | ||
* Only contract owner can call this method. | ||
* @param _token address of claimed token contract, address(0) for native coins. | ||
* @param _to address of tokens receiver | ||
*/ | ||
function claimTokens(address _token, address _to) external onlyOwner { | ||
claimValues(_token, _to); | ||
} | ||
|
||
/** | ||
* @dev Ether receive function. | ||
* Should be only called from the WETH contract when withdrawing native coins. Will revert otherwise. | ||
*/ | ||
receive() external payable { | ||
require(msg.sender == address(WETH)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
pragma solidity 0.7.5; | ||
|
||
interface IERC20Receiver { | ||
function onTokenBridged( | ||
address token, | ||
uint256 value, | ||
bytes calldata data | ||
) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
pragma solidity 0.7.5; | ||
|
||
interface IOmnibridge { | ||
function relayTokens( | ||
address _token, | ||
address _receiver, | ||
uint256 _value | ||
) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
pragma solidity 0.7.5; | ||
|
||
interface IWETH { | ||
function deposit() external payable; | ||
|
||
function withdraw(uint256 _value) external; | ||
|
||
function approve(address _to, uint256 _value) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
pragma solidity 0.7.5; | ||
|
||
import "../interfaces/IERC20Receiver.sol"; | ||
|
||
contract TokenReceiver is IERC20Receiver { | ||
address public token; | ||
address public from; | ||
uint256 public value; | ||
bytes public data; | ||
|
||
function onTokenBridged( | ||
address _token, | ||
uint256 _value, | ||
bytes memory _data | ||
) external override { | ||
token = _token; | ||
from = msg.sender; | ||
value = _value; | ||
data = _data; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
pragma solidity 0.7.5; | ||
|
||
// solhint-disable | ||
contract WETH { | ||
string public name = "Wrapped Ether"; | ||
string public symbol = "WETH"; | ||
uint8 public decimals = 18; | ||
|
||
event Approval(address indexed src, address indexed guy, uint wad); | ||
event Transfer(address indexed src, address indexed dst, uint wad); | ||
event Deposit(address indexed dst, uint wad); | ||
event Withdrawal(address indexed src, uint wad); | ||
|
||
mapping (address => uint) public balanceOf; | ||
mapping (address => mapping (address => uint)) public allowance; | ||
|
||
receive() external payable { | ||
deposit(); | ||
} | ||
function deposit() public payable { | ||
balanceOf[msg.sender] += msg.value; | ||
emit Deposit(msg.sender, msg.value); | ||
} | ||
function withdraw(uint wad) public { | ||
require(balanceOf[msg.sender] >= wad); | ||
balanceOf[msg.sender] -= wad; | ||
msg.sender.transfer(wad); | ||
emit Withdrawal(msg.sender, wad); | ||
} | ||
|
||
function totalSupply() public view returns (uint) { | ||
return address(this).balance; | ||
} | ||
|
||
function approve(address guy, uint wad) public returns (bool) { | ||
allowance[msg.sender][guy] = wad; | ||
emit Approval(msg.sender, guy, wad); | ||
return true; | ||
} | ||
|
||
function transfer(address dst, uint wad) public returns (bool) { | ||
return transferFrom(msg.sender, dst, wad); | ||
} | ||
|
||
function transferFrom(address src, address dst, uint wad) | ||
public | ||
returns (bool) | ||
{ | ||
require(balanceOf[src] >= wad); | ||
|
||
if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) { | ||
require(allowance[src][msg.sender] >= wad); | ||
allowance[src][msg.sender] -= wad; | ||
} | ||
|
||
balanceOf[src] -= wad; | ||
balanceOf[dst] += wad; | ||
|
||
emit Transfer(src, dst, wad); | ||
|
||
return true; | ||
} | ||
} | ||
// solhint-enable |
Oops, something went wrong.