From dd46135248dbb4684752735aab3cf64db170a405 Mon Sep 17 00:00:00 2001 From: Gerardo Nardelli Date: Wed, 29 Jul 2020 15:40:15 -0300 Subject: [PATCH] Remove half duplex erc20 token code (#457) --- contracts/interfaces/IScdMcdMigration.sol | 14 -- .../mocks/ForeignBridgeErcToNativeMock.sol | 15 -- contracts/mocks/SaiTopMock.sol | 9 - contracts/mocks/ScdMcdMigrationMock.sol | 24 --- .../ForeignBridgeErcToNative.sol | 82 +-------- test/erc_to_native/foreign_bridge.test.js | 155 ------------------ 6 files changed, 1 insertion(+), 298 deletions(-) delete mode 100644 contracts/interfaces/IScdMcdMigration.sol delete mode 100644 contracts/mocks/SaiTopMock.sol delete mode 100644 contracts/mocks/ScdMcdMigrationMock.sol diff --git a/contracts/interfaces/IScdMcdMigration.sol b/contracts/interfaces/IScdMcdMigration.sol deleted file mode 100644 index e52a217f..00000000 --- a/contracts/interfaces/IScdMcdMigration.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity 0.4.24; - -interface IScdMcdMigration { - function swapSaiToDai(uint256 wad) external; - function daiJoin() external returns (address); -} - -interface IDaiAdapter { - function dai() public returns (address); -} - -interface ISaiTop { - function caged() public returns (uint256); -} diff --git a/contracts/mocks/ForeignBridgeErcToNativeMock.sol b/contracts/mocks/ForeignBridgeErcToNativeMock.sol index 0306e9ef..4aa33048 100644 --- a/contracts/mocks/ForeignBridgeErcToNativeMock.sol +++ b/contracts/mocks/ForeignBridgeErcToNativeMock.sol @@ -3,21 +3,6 @@ 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); - } - bytes32 internal constant CHAI_TOKEN_MOCK = 0x5d6f4e61a116947624416975e8d26d4aff8f32e21ea6308dfa35cee98ed41fd8; // keccak256(abi.encodePacked("chaiTokenMock")) function setChaiToken(IChai _chaiToken) external { diff --git a/contracts/mocks/SaiTopMock.sol b/contracts/mocks/SaiTopMock.sol deleted file mode 100644 index 5e3d5008..00000000 --- a/contracts/mocks/SaiTopMock.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma solidity 0.4.24; - -contract SaiTopMock { - uint256 public caged; - - function setCaged(uint256 _value) public { - caged = _value; - } -} diff --git a/contracts/mocks/ScdMcdMigrationMock.sol b/contracts/mocks/ScdMcdMigrationMock.sol deleted file mode 100644 index 254ded27..00000000 --- a/contracts/mocks/ScdMcdMigrationMock.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity 0.4.24; - -import "../interfaces/IScdMcdMigration.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol"; - -contract ScdMcdMigrationMock is IScdMcdMigration { - address public sai; - IDaiAdapter public daiJoin; - - constructor(address _sai, address _daiJoin) public { - sai = _sai; - daiJoin = IDaiAdapter(_daiJoin); - } - - function swapSaiToDai(uint256 wad) external { - ERC20(sai).transferFrom(msg.sender, address(this), wad); - MintableToken(daiJoin.dai()).mint(msg.sender, wad); - } - - function daiJoin() external returns (address) { - return daiJoin; - } -} diff --git a/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol b/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol index a5057855..bf56976a 100644 --- a/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol +++ b/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol @@ -3,14 +3,9 @@ pragma solidity 0.4.24; import "../BasicForeignBridge.sol"; import "../ERC20Bridge.sol"; import "../OtherSideBridgeStorage.sol"; -import "../../interfaces/IScdMcdMigration.sol"; import "../ChaiConnector.sol"; contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideBridgeStorage, ChaiConnector { - bytes32 internal constant MIN_HDTOKEN_BALANCE = 0x48649cf195feb695632309f41e61252b09f537943654bde13eb7bb1bca06964e; // keccak256(abi.encodePacked("minHDTokenBalance")) - bytes32 internal constant LOCKED_SAI_FIXED = 0xbeb8b2ece34b32b36c9cc00744143b61b2c23f93adcc3ce78d38937229423051; // keccak256(abi.encodePacked("lockedSaiFixed")) - bytes4 internal constant SWAP_TOKENS = 0x73d00224; // swapTokens() - function initialize( address _validatorContract, address _erc20token, @@ -60,23 +55,10 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB return 0x18762d46; // bytes4(keccak256(abi.encodePacked("erc-to-native-core"))) } - function fixLockedSai(address _receiver) external { - require(msg.sender == address(this)); - require(!boolStorage[LOCKED_SAI_FIXED]); - boolStorage[LOCKED_SAI_FIXED] = true; - setInvestedAmountInDai(investedAmountInDai() + 49938645266079271041); - claimValues(halfDuplexErc20token(), _receiver); - } - function claimTokens(address _token, address _to) public { require(_token != address(erc20token())); // Chai token is not claimable if investing into Chai is enabled require(_token != address(chaiToken()) || !isChaiTokenEnabled()); - 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); } @@ -100,10 +82,6 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB bool res = erc20token().transfer(_recipient, amount); - if (tokenBalance(halfDuplexErc20token()) > 0) { - address(this).call(abi.encodeWithSelector(SWAP_TOKENS)); - } - return res; } @@ -111,64 +89,10 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB revert(); } - function saiTopContract() internal pure returns (ISaiTop) { - return ISaiTop(0x9b0ccf7C8994E19F39b2B4CF708e0A7DF65fA8a3); - } - - function isTokenSwapAllowed( - uint256 /* _ts */ - ) public pure returns (bool) { - return false; - } - - 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).sub(curFDTokenBalance) == curHDTokenBalance); - - emit TokensSwapped(hdToken, fdToken, curHDTokenBalance); - } - function relayTokens(address _receiver, uint256 _amount) external { _relayTokens(msg.sender, _receiver, _amount, erc20token()); } @@ -194,23 +118,19 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB require(withinLimit(_amount)); ERC20 tokenToOperate = ERC20(_token); - ERC20 hdToken = halfDuplexErc20token(); ERC20 fdToken = erc20token(); if (tokenToOperate == ERC20(0x0)) { tokenToOperate = fdToken; } - require(tokenToOperate == fdToken || tokenToOperate == hdToken); + require(tokenToOperate == fdToken); setTotalSpentPerDay(getCurrentDay(), totalSpentPerDay(getCurrentDay()).add(_amount)); tokenToOperate.transferFrom(_sender, address(this), _amount); emit UserRequestForAffirmation(_receiver, _amount); - if (tokenToOperate == hdToken) { - swapTokens(); - } if (isDaiNeedsToBeInvested()) { convertDaiToChai(); } diff --git a/test/erc_to_native/foreign_bridge.test.js b/test/erc_to_native/foreign_bridge.test.js index b333dd69..84e2962a 100644 --- a/test/erc_to_native/foreign_bridge.test.js +++ b/test/erc_to_native/foreign_bridge.test.js @@ -4,9 +4,6 @@ const BridgeValidators = artifacts.require('BridgeValidators.sol') const EternalStorageProxy = artifacts.require('EternalStorageProxy.sol') const ERC677BridgeToken = artifacts.require('ERC677BridgeToken.sol') const ERC20Mock = artifacts.require('ERC20Mock.sol') -const ScdMcdMigrationMock = artifacts.require('ScdMcdMigrationMock.sol') -const DaiAdapterMock = artifacts.require('DaiAdapterMock.sol') -const SaiTopMock = artifacts.require('SaiTopMock.sol') const ForeignBridgeErcToNativeMock = artifacts.require('ForeignBridgeErcToNativeMock.sol') const VatMock = artifacts.require('VatMock') const DaiJoinMock = artifacts.require('DaiJoinMock') @@ -73,8 +70,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { let otherSideBridge let sai let dai - let migrationContract - let saiTop const user = accounts[7] before(async () => { validatorContract = await BridgeValidators.new() @@ -86,16 +81,10 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { // Used account 11 to deploy contracts. The contract addresses will be hardcoded in ForeignBridgeErcToNativeMock const deployAccount = accounts[10] sai = await ERC20Mock.new('sai', 'SAI', 18, { from: deployAccount }) - saiTop = await SaiTopMock.new({ from: deployAccount }) dai = await ERC20Mock.new('dai', 'DAI', 18) - const daiAdapterMock = await DaiAdapterMock.new(dai.address) - migrationContract = await ScdMcdMigrationMock.new(sai.address, daiAdapterMock.address, { from: deployAccount }) await sai.transferOwnership(accounts[0], { from: deployAccount }) await dai.mint(user, ether('100000')) - - // migration contract can mint dai - await dai.transferOwnership(migrationContract.address) }) describe('#initialize', async () => { it('should initialize', async () => { @@ -1182,65 +1171,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { // Mint sai tokens to a user await sai.mint(user, twoEthers) }) - describe('isTokenSwapAllowed', () => { - it('isTokenSwapAllowed should return always false', async () => { - // Given - expect(await foreignBridge.isTokenSwapAllowed(100)).to.be.equal(false) - - // When - await saiTop.setCaged(150) - - // Then - expect(await foreignBridge.isTokenSwapAllowed(100)).to.be.equal(false) - expect(await foreignBridge.isTokenSwapAllowed(150)).to.be.equal(false) - expect(await foreignBridge.isTokenSwapAllowed(200)).to.be.equal(false) - - // reset the caged value - await saiTop.setCaged(0) - }) - }) - describe('isHDTokenBalanceAboveMinBalance', () => { - it('isHDTokenBalanceAboveMinBalance should return true if balance above the threshold ', async () => { - const threshold = halfEther - // Given - expect(await sai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) - - await foreignBridge.setMinHDTokenBalance(threshold) - - expect(await foreignBridge.minHDTokenBalance()).to.be.bignumber.equal(threshold) - - expect(await foreignBridge.isHDTokenBalanceAboveMinBalance()).to.be.equal(false) - - // When - await sai.mint(foreignBridge.address, oneEther) - - // Then - expect(await foreignBridge.isHDTokenBalanceAboveMinBalance()).to.be.equal(true) - }) - }) - describe('halfDuplexErc20token', () => { - it('should be able to get half duplex erc20 token', async () => { - expect(await foreignBridge.halfDuplexErc20token()).to.be.equal(sai.address) - }) - }) - describe('swapTokens', () => { - it('should not be able to swap tokens calling swapTokens', async () => { - expect(await saiTop.caged()).to.be.bignumber.equal(ZERO) - expect(await sai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) - expect(await dai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) - - // should have sai balance - await foreignBridge.swapTokens().should.be.rejectedWith(ERROR_MSG) - - // mint sai tokens to bridge - await sai.mint(foreignBridge.address, oneEther) - - expect(await sai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(oneEther) - expect(await dai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) - - await foreignBridge.swapTokens().should.be.rejectedWith(ERROR_MSG) - }) - }) describe('relayTokens', () => { const value = ether('0.25') it('should allow to bridge tokens specifying the token address', async () => { @@ -1291,20 +1221,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { }) expect(await dai.balanceOf(user)).to.be.bignumber.equal(balance.sub(value)) }) - it('should not swap token if half duplex token is used', async () => { - // Given - const relayTokens = foreignBridge.methods['relayTokens(address,uint256,address)'] - - expect(await sai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) - expect(await dai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) - const currentDay = await foreignBridge.getCurrentDay() - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - - await sai.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled - - // When - await relayTokens(recipient, value, sai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - }) it('should fail if token address is unknown', async () => { const otherToken = await ERC20Mock.new('token', 'TOK', 18) await otherToken.mint(user, twoEthers) @@ -1435,37 +1351,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { expect(await chaiToken.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) }) }) - describe('onExecuteMessage', () => { - it('should not swap Tokens in executeSignatures', async () => { - const value = ether('0.25') - const recipientAccount = accounts[3] - const balanceBefore = await dai.balanceOf(recipientAccount) - - // fund dai tokens - await dai.transfer(foreignBridge.address, value, { from: user }) - - // mint sai tokens to bridge - await sai.mint(foreignBridge.address, halfEther) - - const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80' - const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address) - const signature = await sign(authorities[0], message) - const vrs = signatureToVRS(signature) - const oneSignature = packSignatures([vrs]) - expect(await foreignBridge.relayedMessages(transactionHash)).to.be.equal(false) - - const { logs } = await foreignBridge.executeSignatures(message, oneSignature).should.be.fulfilled - - expectEventInLogs(logs, 'RelayedMessage', { - recipient: recipientAccount, - value - }) - expect(await dai.balanceOf(recipientAccount)).to.be.bignumber.equal(balanceBefore.add(value)) - expect(await sai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(halfEther) - expect(await dai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) - expect(await foreignBridge.relayedMessages(transactionHash)).to.be.equal(true) - }) - }) describe('claimTokens', async () => { it('can send erc20', async () => { const foreignBridgeImpl = await ForeignBridgeErcToNativeMock.new() @@ -1485,8 +1370,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { otherSideBridge.address ) - expect(await saiTop.caged()).to.be.bignumber.equal(ZERO) - // Mint sai tokens to the bridge await sai.mint(foreignBridge.address, halfEther) @@ -1499,9 +1382,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { await foreignBridge.claimTokens(sai.address, accounts[3], { from: owner }) expect(await sai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) expect(await sai.balanceOf(accounts[3])).to.be.bignumber.equal(halfEther) - - // reset the caged value - await saiTop.setCaged(0) }) }) }) @@ -2214,40 +2094,5 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { } }) }) - - describe('fixLockedSai', async () => { - it('should fix 49.938645266079271041 locked sai tokens', async () => { - const foreignBridgeProxy = await EternalStorageProxy.new().should.be.fulfilled - await foreignBridgeProxy.upgradeTo('1', foreignBridge.address).should.be.fulfilled - foreignBridge = await ForeignBridge.at(foreignBridgeProxy.address) - await foreignBridge.initialize( - validatorContract.address, - token.address, - requireBlockConfirmations, - gasPrice, - [dailyLimit, maxPerTx, minPerTx], - [homeDailyLimit, homeMaxPerTx], - owner, - decimalShiftZero, - otherSideBridge.address - ).should.be.fulfilled - - await sai.mint(foreignBridge.address, 100) - - const foreignBridge2 = await ForeignBridgeErcToNativeMock.new() - const foreignBridge3 = await ForeignBridgeErcToNativeMock.new() - - const data = foreignBridge.contract.methods.fixLockedSai(accounts[9]).encodeABI() - - await foreignBridgeProxy.upgradeToAndCall('2', foreignBridge2.address, data).should.be.fulfilled - - await sai.mint(foreignBridge.address, 100) - - await foreignBridgeProxy.upgradeToAndCall('3', foreignBridge3.address, data).should.be.rejected - - expect(await sai.balanceOf(accounts[9])).to.be.bignumber.equal('100') - expect(await foreignBridge.investedAmountInDai()).to.be.bignumber.equal('49938645266079271041') - }) - }) }) })