-
Notifications
You must be signed in to change notification settings - Fork 219
Add support for two tokens in erc to native #319
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
Changes from 8 commits
b9cff12
e29e78f
71e62eb
7fdac53
ede2c50
94b2a85
360dcaa
055bcb6
be3cd33
c2c2c4c
251f949
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| pragma solidity 0.4.24; | ||
|
|
||
| import "../upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol"; | ||
|
|
||
| contract ForeignBridgeErcToNativeMock is ForeignBridgeErcToNative { | ||
| function migrationContract() internal pure returns (IScdMcdMigration) { | ||
| // Address generated in unit test | ||
| return IScdMcdMigration(0x44Bf5539DAAc4259f7F11A24280255ED2Fa3F7BF); | ||
| } | ||
|
|
||
| function halfDuplexErc20token() public pure returns (ERC20) { | ||
| // Address generated in unit test | ||
| return ERC20(0x872D709De609c391741c7595F0053F6060e59e0D); | ||
| } | ||
|
|
||
| function saiTopContract() internal pure returns (ISaiTop) { | ||
| // Address generated in unit test | ||
| return ISaiTop(0x96bc48adACdB60E6536E55a6727919a397F14540); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| pragma solidity 0.4.24; | ||
|
|
||
| contract SaiTopMock { | ||
| uint256 public caged; | ||
|
|
||
| function setCaged(uint256 _value) public { | ||
| caged = _value; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,9 @@ import "../../interfaces/IScdMcdMigration.sol"; | |
| contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideBridgeStorage { | ||
| event TokensSwapped(address indexed from, address indexed to, uint256 value); | ||
|
|
||
| bytes32 internal constant MIN_HDTOKEN_BALANCE = 0x48649cf195feb695632309f41e61252b09f537943654bde13eb7bb1bca06964e; // keccak256(abi.encodePacked("minHDTokenBalance")) | ||
| bytes4 internal constant SWAP_TOKENS = 0x73d00224; // swapTokens() | ||
|
|
||
| function initialize( | ||
| address _validatorContract, | ||
| address _erc20token, | ||
|
|
@@ -61,6 +64,11 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB | |
|
|
||
| function claimTokens(address _token, address _to) public { | ||
| require(_token != address(erc20token())); | ||
| if (_token == address(halfDuplexErc20token())) { | ||
| // SCD is not claimable if the bridge accepts deposits of this token | ||
| // solhint-disable-next-line not-rely-on-time | ||
| require(!isTokenSwapAllowed(now)); | ||
| } | ||
| super.claimTokens(_token, _to); | ||
| } | ||
|
|
||
|
|
@@ -71,7 +79,13 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB | |
| ) internal returns (bool) { | ||
| setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_amount)); | ||
| uint256 amount = _amount.div(10**decimalShift()); | ||
| return erc20token().transfer(_recipient, amount); | ||
| bool res = erc20token().transfer(_recipient, amount); | ||
|
|
||
| if (tokenBalance(halfDuplexErc20token()) > 0) { | ||
| address(this).call(abi.encodeWithSelector(SWAP_TOKENS)); | ||
| } | ||
|
|
||
| return res; | ||
| } | ||
|
|
||
| function onFailedMessage(address, uint256, bytes32) internal { | ||
|
|
@@ -83,23 +97,113 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB | |
| super._relayTokens(_sender, _receiver, _amount); | ||
| } | ||
|
|
||
| function migrateToMCD(address _migrationContract) external onlyOwner { | ||
| function migrateToMCD() external onlyOwner { | ||
|
||
| bytes32 storageAddress = 0x3378953eb16363e06fd9ea9701d36ed7285d206d9de7df55b778462d74596a89; // keccak256(abi.encodePacked("migrationToMcdCompleted")) | ||
|
|
||
| require(!boolStorage[storageAddress]); | ||
| require(AddressUtils.isContract(_migrationContract)); | ||
|
|
||
| uint256 curBalance = erc20token().balanceOf(address(this)); | ||
| require(erc20token().approve(_migrationContract, curBalance)); | ||
| //It is important to note that this action will cause appearing of `Transfer` | ||
| //event as part of the tokens minting | ||
| IScdMcdMigration(_migrationContract).swapSaiToDai(curBalance); | ||
| address saiContract = erc20token(); | ||
| address mcdContract = IDaiAdapter(IScdMcdMigration(_migrationContract).daiJoin()).dai(); | ||
|
|
||
| address mcdContract = IDaiAdapter(migrationContract().daiJoin()).dai(); | ||
| setErc20token(mcdContract); | ||
| require(erc20token().balanceOf(address(this)) == curBalance); | ||
|
|
||
| emit TokensSwapped(saiContract, erc20token(), curBalance); | ||
| uintStorage[MIN_HDTOKEN_BALANCE] = 10 ether; | ||
|
|
||
| swapTokens(); | ||
|
|
||
| boolStorage[storageAddress] = true; | ||
| } | ||
|
|
||
| function saiTopContract() internal pure returns (ISaiTop) { | ||
| return ISaiTop(0x9b0ccf7C8994E19F39b2B4CF708e0A7DF65fA8a3); | ||
| } | ||
|
|
||
| function isTokenSwapAllowed(uint256 _ts) public view returns (bool) { | ||
| uint256 esTs = saiTopContract().caged(); | ||
| if (esTs > 0 && _ts > esTs) { | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| function halfDuplexErc20token() public pure returns (ERC20) { | ||
| return ERC20(0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359); | ||
| } | ||
|
|
||
| function setMinHDTokenBalance(uint256 _minBalance) external onlyOwner { | ||
akolotov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| uintStorage[MIN_HDTOKEN_BALANCE] = _minBalance; | ||
| } | ||
|
|
||
| function minHDTokenBalance() public view returns (uint256) { | ||
| return uintStorage[MIN_HDTOKEN_BALANCE]; | ||
| } | ||
|
|
||
| function isHDTokenBalanceAboveMinBalance() public view returns (bool) { | ||
| if (tokenBalance(halfDuplexErc20token()) > minHDTokenBalance()) { | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| function tokenBalance(ERC20 _token) internal view returns (uint256) { | ||
| return _token.balanceOf(address(this)); | ||
| } | ||
|
|
||
| function migrationContract() internal pure returns (IScdMcdMigration) { | ||
akolotov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return IScdMcdMigration(0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849); | ||
| } | ||
|
|
||
| function swapTokens() public { | ||
akolotov marked this conversation as resolved.
Show resolved
Hide resolved
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we increase the version returned by
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it makes sense. Updated to |
||
| // solhint-disable-next-line not-rely-on-time | ||
| require(isTokenSwapAllowed(now)); | ||
|
|
||
| IScdMcdMigration mcdMigrationContract = migrationContract(); | ||
| ERC20 hdToken = halfDuplexErc20token(); | ||
| ERC20 fdToken = erc20token(); | ||
|
|
||
| uint256 curHDTokenBalance = tokenBalance(hdToken); | ||
| require(curHDTokenBalance > 0); | ||
|
|
||
| uint256 curFDTokenBalance = tokenBalance(fdToken); | ||
|
|
||
| require(hdToken.approve(mcdMigrationContract, curHDTokenBalance)); | ||
| mcdMigrationContract.swapSaiToDai(curHDTokenBalance); | ||
|
|
||
| require(tokenBalance(fdToken).sub(curFDTokenBalance) == curHDTokenBalance); | ||
|
|
||
| emit TokensSwapped(hdToken, fdToken, curHDTokenBalance); | ||
| } | ||
|
|
||
| function relayTokens(address _from, address _receiver, uint256 _amount, address _token) external { | ||
| require(_from == msg.sender || _from == _receiver); | ||
| _relayTokens(_from, _receiver, _amount, _token); | ||
| } | ||
|
|
||
| function relayTokens(address _receiver, uint256 _amount, address _token) external { | ||
| _relayTokens(msg.sender, _receiver, _amount, _token); | ||
| } | ||
|
|
||
| function _relayTokens(address _sender, address _receiver, uint256 _amount, address _token) internal { | ||
| require(_receiver != bridgeContractOnOtherSide()); | ||
| require(_receiver != address(0)); | ||
| require(_receiver != address(this)); | ||
| require(_amount > 0); | ||
| require(withinLimit(_amount)); | ||
|
|
||
| ERC20 tokenToOperate = ERC20(_token); | ||
| ERC20 hdToken = halfDuplexErc20token(); | ||
| ERC20 fdToken = erc20token(); | ||
|
|
||
| if (tokenToOperate == ERC20(0x0)) { | ||
| tokenToOperate = fdToken; | ||
| } | ||
|
|
||
| require(tokenToOperate == fdToken || tokenToOperate == hdToken); | ||
|
|
||
| setTotalSpentPerDay(getCurrentDay(), totalSpentPerDay(getCurrentDay()).add(_amount)); | ||
|
|
||
| tokenToOperate.transferFrom(_sender, address(this), _amount); | ||
| emit UserRequestForAffirmation(_receiver, _amount); | ||
|
|
||
| if (tokenToOperate == hdToken) { | ||
| swapTokens(); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we increase a version in
getBridgeValidatorsInterfacesVersion?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should. Updated version to
2.3.0be3cd33