Skip to content

Commit

Permalink
Add support for two tokens in erc to native
Browse files Browse the repository at this point in the history
  • Loading branch information
patitonar committed Nov 20, 2019
1 parent 20d2627 commit b9cff12
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 1 deletion.
4 changes: 4 additions & 0 deletions contracts/interfaces/IScdMcdMigration.sol
Expand Up @@ -8,3 +8,7 @@ interface IScdMcdMigration {
interface IDaiAdapter {
function dai() public returns (address);
}

interface ISaiTop {
function caged() public returns (uint256);
}
19 changes: 19 additions & 0 deletions contracts/upgradeable_contracts/BaseBridgeValidators.sol
Expand Up @@ -102,4 +102,23 @@ contract BaseBridgeValidators is InitializableBridge, Ownable {
function setNextValidator(address _prevValidator, address _validator) internal {
addressStorage[keccak256(abi.encodePacked("validatorsList", _prevValidator))] = _validator;
}

function isValidatorDuty(address _validator) external view returns (bool) {
uint256 counter = 0;
address next = getNextValidator(F_ADDR);
require(next != address(0));

while (next != F_ADDR) {
if (next == _validator) {
return (block.number % validatorCount() == counter);
}

next = getNextValidator(next);
counter++;

require(next != address(0));
}

return false;
}
}
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}

Expand All @@ -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 (AddressUtils.isContract(halfDuplexErc20token()) && tokenBalance(halfDuplexErc20token()) > 0) {
address(this).call(abi.encodeWithSelector(SWAP_TOKENS));
}

return res;
}

function onFailedMessage(address, uint256, bytes32) internal {
Expand Down Expand Up @@ -102,4 +116,100 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB
emit TokensSwapped(saiContract, erc20token(), curBalance);
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 {
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) {
return IScdMcdMigration(0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849);
}

function swapTokens() public {
// 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) - 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();
}
}
}

0 comments on commit b9cff12

Please sign in to comment.