Add method to migrate from SCD to MCD (#311)
This commit is contained in:
parent
7bf4e0629a
commit
cc7718284d
|
@ -0,0 +1,10 @@
|
|||
pragma solidity 0.4.24;
|
||||
|
||||
interface IScdMcdMigration {
|
||||
function swapSaiToDai(uint256 wad) external;
|
||||
function daiJoin() external returns (address);
|
||||
}
|
||||
|
||||
interface IDaiAdapter {
|
||||
function dai() public returns (address);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
pragma solidity 0.4.24;
|
||||
|
||||
contract DaiAdapterMock {
|
||||
address public dai;
|
||||
|
||||
constructor(address _dai) public {
|
||||
dai = _dai;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -3,8 +3,11 @@ pragma solidity 0.4.24;
|
|||
import "../BasicForeignBridge.sol";
|
||||
import "../ERC20Bridge.sol";
|
||||
import "../OtherSideBridgeStorage.sol";
|
||||
import "../../interfaces/IScdMcdMigration.sol";
|
||||
|
||||
contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideBridgeStorage {
|
||||
event TokensSwapped(address indexed from, address indexed to, uint256 value);
|
||||
|
||||
function initialize(
|
||||
address _validatorContract,
|
||||
address _erc20token,
|
||||
|
@ -79,4 +82,24 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB
|
|||
require(_receiver != bridgeContractOnOtherSide());
|
||||
super._relayTokens(_sender, _receiver, _amount);
|
||||
}
|
||||
|
||||
function migrateToMCD(address _migrationContract) 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();
|
||||
setErc20token(mcdContract);
|
||||
require(erc20token().balanceOf(address(this)) == curBalance);
|
||||
|
||||
emit TokensSwapped(saiContract, erc20token(), curBalance);
|
||||
boolStorage[storageAddress] = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,13 @@ const ForeignBridgeV2 = artifacts.require('ForeignBridgeV2.sol')
|
|||
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 { expect } = require('chai')
|
||||
const { ERROR_MSG, ZERO_ADDRESS, toBN } = require('../setup')
|
||||
const { createMessage, sign, signatureToVRS, ether, expectEventInLogs } = require('../helpers/helpers')
|
||||
const { createMessage, sign, signatureToVRS, ether, expectEventInLogs, getEvents } = require('../helpers/helpers')
|
||||
|
||||
const halfEther = ether('0.5')
|
||||
const requireBlockConfirmations = 8
|
||||
|
@ -834,4 +837,71 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => {
|
|||
})
|
||||
})
|
||||
})
|
||||
describe('migrateToMCD', () => {
|
||||
let foreignBridge
|
||||
let sai
|
||||
let dai
|
||||
let migrationContract
|
||||
beforeEach(async () => {
|
||||
foreignBridge = await ForeignBridge.new()
|
||||
sai = await ERC20Mock.new('sai', 'SAI', 18)
|
||||
dai = await ERC20Mock.new('dai', 'DAI', 18)
|
||||
const daiAdapterMock = await DaiAdapterMock.new(dai.address)
|
||||
migrationContract = await ScdMcdMigrationMock.new(sai.address, daiAdapterMock.address)
|
||||
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
sai.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero,
|
||||
otherSideBridge.address
|
||||
)
|
||||
|
||||
// Mint the bridge some sai tokens
|
||||
await sai.mint(foreignBridge.address, oneEther)
|
||||
|
||||
// migration contract can mint dai
|
||||
await dai.transferOwnership(migrationContract.address)
|
||||
})
|
||||
it('should be able to swap tokens', async () => {
|
||||
// Given
|
||||
expect(await sai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(oneEther)
|
||||
expect(await dai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO)
|
||||
expect(await foreignBridge.erc20token()).to.be.equal(sai.address)
|
||||
|
||||
// When
|
||||
|
||||
// migration address should be a contract
|
||||
await foreignBridge.migrateToMCD(accounts[3], { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
// should be called by owner
|
||||
await foreignBridge
|
||||
.migrateToMCD(migrationContract.address, { from: accounts[5] })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
const { logs } = await foreignBridge.migrateToMCD(migrationContract.address, { from: owner }).should.be.fulfilled
|
||||
|
||||
// can't migrate token again
|
||||
await foreignBridge.migrateToMCD(migrationContract.address, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
// Then
|
||||
expect(await sai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO)
|
||||
expect(await dai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(oneEther)
|
||||
expect(await foreignBridge.erc20token()).to.be.equal(dai.address)
|
||||
expectEventInLogs(logs, 'TokensSwapped', {
|
||||
from: sai.address,
|
||||
to: dai.address,
|
||||
value: oneEther
|
||||
})
|
||||
const transferEvent = await getEvents(dai, { event: 'Transfer' })
|
||||
expect(transferEvent.length).to.be.equal(1)
|
||||
expect(transferEvent[0].returnValues.from).to.be.equal(ZERO_ADDRESS)
|
||||
expect(transferEvent[0].returnValues.to).to.be.equal(foreignBridge.address)
|
||||
expect(transferEvent[0].returnValues.value).to.be.equal(oneEther.toString())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue