From 5cedacafe58f413d835419484fd552f52d72f819 Mon Sep 17 00:00:00 2001 From: Kirill Fedoseev Date: Tue, 24 Aug 2021 11:31:15 +0300 Subject: [PATCH] Fix handling of Compound related Transfer events (#595) --- e2e-commons/constants.json | 2 +- e2e-commons/contracts-envs/erc-to-native.env | 2 +- monitor/getBalances.js | 39 +------- monitor/utils/events.js | 93 +++++--------------- monitor/utils/tokenUtils.js | 27 ------ oracle-e2e/test/ercToNative.js | 5 ++ oracle/src/confirmRelay.js | 9 +- oracle/src/events/processTransfers/index.js | 63 +++++++------ oracle/src/watcher.js | 4 +- parity/chain-foreign.json | 9 +- parity/foreign_mocks/cDAIMock.sol | 33 +++++++ 11 files changed, 121 insertions(+), 165 deletions(-) delete mode 100644 monitor/utils/tokenUtils.js create mode 100644 parity/foreign_mocks/cDAIMock.sol diff --git a/e2e-commons/constants.json b/e2e-commons/constants.json index 9eb9bced..4dd864ff 100644 --- a/e2e-commons/constants.json +++ b/e2e-commons/constants.json @@ -38,7 +38,7 @@ "ercToNativeBridge": { "home": "0x5118AC62AE912Dd5B51EEfF7338c4fcb0248Ba8c", "foreign": "0x32198D570fffC7033641F8A9094FFDCaAEF42624", - "foreignToken": "0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9", + "foreignToken": "0x6B175474E89094C44Da98b954EedeAC495271d0F", "monitor": "http://monitor-erc20-native:3012/bridge" }, "amb": { diff --git a/e2e-commons/contracts-envs/erc-to-native.env b/e2e-commons/contracts-envs/erc-to-native.env index efcb8947..421d998e 100644 --- a/e2e-commons/contracts-envs/erc-to-native.env +++ b/e2e-commons/contracts-envs/erc-to-native.env @@ -32,7 +32,7 @@ FOREIGN_GAS_PRICE=10000000000 FOREIGN_REWARDABLE=false BLOCK_REWARD_ADDRESS=0xdbeE25CbE97e4A5CC6c499875774dc7067E9426B -ERC20_TOKEN_ADDRESS=0x7cc4b1851c35959d34e635a470f6b5c43ba3c9c9 +ERC20_TOKEN_ADDRESS=0x6B175474E89094C44Da98b954EedeAC495271d0F REQUIRED_NUMBER_OF_VALIDATORS=1 VALIDATORS="0xaaB52d66283F7A1D5978bcFcB55721ACB467384b 0xdCC784657C78054aa61FbcFFd2605F32374816A4 0xDcef88209a20D52165230104B245803C3269454d" diff --git a/monitor/getBalances.js b/monitor/getBalances.js index 559b7e08..3cd5655c 100644 --- a/monitor/getBalances.js +++ b/monitor/getBalances.js @@ -46,24 +46,6 @@ async function main(bridgeMode, eventsInfo) { const foreignBridge = new web3Foreign.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS) const erc20Address = await foreignBridge.methods.erc20token().call() const erc20Contract = new web3Foreign.eth.Contract(ERC20_ABI, erc20Address) - let investedAmountInDai = 0 - let bridgeDsrBalance = 0 - let displayChaiToken = false - - try { - logger.debug('calling foreignBridge.methods.isChaiTokenEnabled') - if (await foreignBridge.methods.isChaiTokenEnabled().call()) { - displayChaiToken = true - logger.debug('calling foreignBridge.methods.investedAmountInDai') - investedAmountInDai = await foreignBridge.methods.investedAmountInDai().call() - logger.debug('calling foreignBridge.methods.dsrBalance') - bridgeDsrBalance = await foreignBridge.methods.dsrBalance().call() - } else { - logger.debug('Chai token is currently disabled') - } - } catch (e) { - logger.debug('Methods for chai token are not present') - } logger.debug('calling erc20Contract.methods.balanceOf') const foreignErc20Balance = await erc20Contract.methods @@ -85,29 +67,16 @@ async function main(bridgeMode, eventsInfo) { const burntCoinsBN = new BN(burntCoins) const totalSupplyBN = mintedCoinsBN.minus(burntCoinsBN) const foreignErc20BalanceBN = new BN(foreignErc20Balance).plus(lateForeignConfirmationsTotalValue) - const investedAmountInDaiBN = new BN(investedAmountInDai) - const bridgeDsrBalanceBN = new BN(bridgeDsrBalance) - - const diff = foreignErc20BalanceBN - .plus(investedAmountInDaiBN) - .minus(totalSupplyBN) - .toFixed() - - const foreign = { - erc20Balance: Web3Utils.fromWei(foreignErc20Balance) - } - - if (displayChaiToken) { - foreign.investedErc20Balance = Web3Utils.fromWei(investedAmountInDai) - foreign.accumulatedInterest = Web3Utils.fromWei(bridgeDsrBalanceBN.minus(investedAmountInDaiBN).toString(10)) - } + const diff = foreignErc20BalanceBN.minus(totalSupplyBN).toFixed() logger.debug('Done') return { home: { totalSupply: Web3Utils.fromWei(totalSupplyBN.toFixed()) }, - foreign, + foreign: { + erc20Balance: Web3Utils.fromWei(foreignErc20Balance) + }, balanceDiff: Number(Web3Utils.fromWei(diff)), ...blockRanges, lastChecked: Math.floor(Date.now() / 1000) diff --git a/monitor/utils/events.js b/monitor/utils/events.js index e2bbdeff..a7792da8 100644 --- a/monitor/utils/events.js +++ b/monitor/utils/events.js @@ -11,7 +11,6 @@ const { OLD_AMB_USER_REQUEST_FOR_AFFIRMATION_ABI } = require('../../commons') const { normalizeEventInformation } = require('./message') -const { filterTransferBeforeES } = require('./tokenUtils') const { writeFile, readCacheFile } = require('./file') const { web3Home, web3Foreign, getHomeBlockNumber, getForeignBlockNumber } = require('./web3') const { getPastEvents } = require('./web3Cache') @@ -160,80 +159,32 @@ async function main(mode) { filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS } }, chain: 'foreign' + })) + .map(normalizeEvent) + .filter(e => e.recipient !== ZERO_ADDRESS) // filter mint operation during SCD-to-MCD swaps + .filter(e => e.recipient.toLowerCase() !== '0x5d3a536e4d6dbd6114cc1ead35777bab948e3643') // filter cDai withdraws during compounding + + // Get transfer events for each previously used Sai token + const saiTokenAddress = '0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359' + const halfDuplexTokenContract = new web3Foreign.eth.Contract(ERC20_ABI, saiTokenAddress) + logger.debug('Half duplex token:', saiTokenAddress) + logger.debug("calling halfDuplexTokenContract.getPastEvents('Transfer')") + // https://etherscan.io/tx/0xd0c3c92c94e05bc71256055ce8c4c993e047f04e04f3283a04e4cb077b71f6c6 + const blockNumberHalfDuplexDisabled = 9884448 + const halfDuplexTransferEvents = (await getPastEvents(halfDuplexTokenContract, { + event: 'Transfer', + fromBlock: MONITOR_FOREIGN_START_BLOCK, + toBlock: Math.min(blockNumberHalfDuplexDisabled, foreignDelayedBlockNumber), + options: { + filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS } + }, + chain: 'foreign' })).map(normalizeEvent) - let directTransfers = transferEvents - const tokensSwappedAbiExists = FOREIGN_ABI.filter(e => e.type === 'event' && e.name === 'TokensSwapped')[0] - if (tokensSwappedAbiExists) { - logger.debug('collecting half duplex tokens participated in the bridge balance') - logger.debug("calling foreignBridge.getPastEvents('TokensSwapped')") - const tokensSwappedEvents = await getPastEvents(foreignBridge, { - event: 'TokensSwapped', - fromBlock: MONITOR_FOREIGN_START_BLOCK, - toBlock: foreignBlockNumber, - chain: 'foreign', - safeToBlock: foreignDelayedBlockNumber - }) - - // Get token swap events emitted by foreign bridge - const bridgeTokensSwappedEvents = tokensSwappedEvents.filter(e => e.address === COMMON_FOREIGN_BRIDGE_ADDRESS) - - // Get transfer events for each previous erc20 - const uniqueTokenAddressesSet = new Set(bridgeTokensSwappedEvents.map(e => e.returnValues.from)) - - // Exclude chai token from previous erc20 - try { - logger.debug('calling foreignBridge.chaiToken() to remove it from half duplex tokens list') - const chaiToken = await foreignBridge.methods.chaiToken().call() - uniqueTokenAddressesSet.delete(chaiToken) - } catch (e) { - logger.debug('call to foreignBridge.chaiToken() failed') - } - // Exclude dai token from previous erc20 - try { - logger.debug('calling foreignBridge.erc20token() to remove it from half duplex tokens list') - const daiToken = await foreignBridge.methods.erc20token().call() - uniqueTokenAddressesSet.delete(daiToken) - } catch (e) { - logger.debug('call to foreignBridge.erc20token() failed') - } - - const uniqueTokenAddresses = [...uniqueTokenAddressesSet] - await Promise.all( - uniqueTokenAddresses.map(async tokenAddress => { - const halfDuplexTokenContract = new web3Foreign.eth.Contract(ERC20_ABI, tokenAddress) - - logger.debug('Half duplex token:', tokenAddress) - logger.debug("calling halfDuplexTokenContract.getPastEvents('Transfer')") - const halfDuplexTransferEvents = (await getPastEvents(halfDuplexTokenContract, { - event: 'Transfer', - fromBlock: MONITOR_FOREIGN_START_BLOCK, - toBlock: foreignDelayedBlockNumber, - options: { - filter: { to: COMMON_FOREIGN_BRIDGE_ADDRESS } - }, - chain: 'foreign' - })).map(normalizeEvent) - - // Remove events after the ES - logger.debug('filtering half duplex transfers happened before ES') - const validHalfDuplexTransfers = await filterTransferBeforeES(halfDuplexTransferEvents) - - transferEvents = [...validHalfDuplexTransfers, ...transferEvents] - }) - ) - - // filter transfer that is part of a token swap - directTransfers = transferEvents.filter( - e => - bridgeTokensSwappedEvents.findIndex( - t => t.transactionHash === e.referenceTx && e.recipient === ZERO_ADDRESS - ) === -1 - ) - } + transferEvents = [...halfDuplexTransferEvents, ...transferEvents] // Get transfer events that didn't have a UserRequestForAffirmation event in the same transaction - directTransfers = directTransfers.filter( + const directTransfers = transferEvents.filter( e => foreignToHomeRequests.findIndex(t => t.referenceTx === e.referenceTx) === -1 ) diff --git a/monitor/utils/tokenUtils.js b/monitor/utils/tokenUtils.js deleted file mode 100644 index 83543a86..00000000 --- a/monitor/utils/tokenUtils.js +++ /dev/null @@ -1,27 +0,0 @@ -// https://etherscan.io/tx/0xd0c3c92c94e05bc71256055ce8c4c993e047f04e04f3283a04e4cb077b71f6c6 -const blockNumberHalfDuplexDisabled = 9884448 - -/** - * Returns true if the event was before the bridge stopped supporting half duplex transfers. - */ -async function transferBeforeES(event) { - return event.blockNumber < blockNumberHalfDuplexDisabled -} - -async function filterTransferBeforeES(array) { - const newArray = [] - // Iterate events from newer to older - for (let i = array.length - 1; i >= 0; i--) { - const beforeES = await transferBeforeES(array[i]) - if (beforeES) { - // add element to first position so the new array will have the same order - newArray.unshift(array[i]) - } - } - return newArray -} - -module.exports = { - filterTransferBeforeES, - blockNumberHalfDuplexDisabled -} diff --git a/oracle-e2e/test/ercToNative.js b/oracle-e2e/test/ercToNative.js index 7a0352c4..d8af0c3a 100644 --- a/oracle-e2e/test/ercToNative.js +++ b/oracle-e2e/test/ercToNative.js @@ -33,6 +33,10 @@ const homeBridge = new homeWeb3.eth.Contract(HOME_ERC_TO_NATIVE_ABI, COMMON_HOME describe('erc to native', () => { before(async () => { + console.log('Initializing interest') + await foreignBridge.methods + .initializeInterest(ercToNativeBridge.foreignToken, 1, 1, validator.address) + .send({ from: validator.address, gas: '4000000' }) if (process.env.ULTIMATE === 'true') { return } @@ -112,6 +116,7 @@ describe('erc to native', () => { .catch(e => { console.error(e) }) + await foreignBridge.methods.investDai().send({ from: validator.address, gas: '4000000' }) // check that balance increases await uniformRetry(async retry => { diff --git a/oracle/src/confirmRelay.js b/oracle/src/confirmRelay.js index 64790951..af081e6a 100644 --- a/oracle/src/confirmRelay.js +++ b/oracle/src/confirmRelay.js @@ -6,6 +6,7 @@ const logger = require('./services/logger') const GasPrice = require('./services/gasPrice') const { getNonce, getChainId, getEventsFromTx } = require('./tx/web3') const { sendTx } = require('./tx/sendTx') +const { getTokensState } = require('./utils/tokenState') const { checkHTTPS, watchdog, syncForEach, addExtraGas } = require('./utils/utils') const { EXIT_CODES, EXTRA_GAS_PERCENTAGE, MAX_GAS_LIMIT } = require('./utils/constants') @@ -17,7 +18,7 @@ if (process.argv.length < 4) { } const config = require(path.join('../config/', process.argv[2])) -const { web3, eventContract, chain } = config.main +const { web3, eventContract, chain, bridgeContract } = config.main const isTxHash = txHash => txHash.length === 66 && web3.utils.isHexStrict(txHash) function readTxHashes(filePath) { @@ -114,6 +115,12 @@ function processEvents(events) { } async function main({ sendJob, txHashes }) { + if (config.id === 'erc-native-transfer') { + logger.debug('Getting token address to listen Transfer events') + const state = await getTokensState(bridgeContract, logger) + eventContract.options.address = state.bridgeableTokenAddress + } + logger.info(`Processing ${txHashes.length} input transactions`) for (const txHash of txHashes) { try { diff --git a/oracle/src/events/processTransfers/index.js b/oracle/src/events/processTransfers/index.js index 420dff8c..333ec374 100644 --- a/oracle/src/events/processTransfers/index.js +++ b/oracle/src/events/processTransfers/index.js @@ -13,12 +13,25 @@ const limit = promiseLimit(MAX_CONCURRENT_EVENTS) function processTransfersBuilder(config) { const { bridgeContract, web3 } = config.home - const userRequestForAffirmationAbi = config.foreign.bridgeABI.find( - e => e.type === 'event' && e.name === 'UserRequestForAffirmation' - ) - const tokensSwappedAbi = config.foreign.bridgeABI.find(e => e.type === 'event' && e.name === 'TokensSwapped') - const userRequestForAffirmationHash = web3.eth.abi.encodeEventSignature(userRequestForAffirmationAbi) - const tokensSwappedHash = tokensSwappedAbi ? web3.eth.abi.encodeEventSignature(tokensSwappedAbi) : '0x' + const userRequestForAffirmationHash = web3.eth.abi.encodeEventSignature('UserRequestForAffirmation(address,uint256)') + const redeemHash = web3.eth.abi.encodeEventSignature('Redeem(address,uint256,uint256)') + const transferHash = web3.eth.abi.encodeEventSignature('Transfer(address,address,uint256)') + + const foreignBridgeAddress = config.foreign.bridgeAddress + + const decodeAddress = data => web3.eth.abi.decodeParameter('address', data) + + const isUserRequestForAffirmation = e => + e.address.toLowerCase() === foreignBridgeAddress.toLowerCase() && e.topics[0] === userRequestForAffirmationHash + const isRedeem = cTokenAddress => e => + e.address.toLowerCase() === cTokenAddress.toLowerCase() && + e.topics[0] === redeemHash && + decodeAddress(e.data.slice(0, 66)).toLowerCase() === foreignBridgeAddress.toLowerCase() + const isCTokenTransfer = cTokenAddress => e => + e.address.toLowerCase() === cTokenAddress.toLowerCase() && + e.topics[0] === transferHash && + decodeAddress(e.topics[1]).toLowerCase() === foreignBridgeAddress.toLowerCase() && + decodeAddress(e.topics[2]).toLowerCase() === cTokenAddress.toLowerCase() let validatorContract = null @@ -32,37 +45,35 @@ function processTransfersBuilder(config) { rootLogger.debug(`Processing ${transfers.length} Transfer events`) const callbacks = transfers .map(transfer => async () => { - const { from, value } = transfer.returnValues + const { from, to, value } = transfer.returnValues const logger = rootLogger.child({ - eventTransactionHash: transfer.transactionHash + eventTransactionHash: transfer.transactionHash, + from, + to, + value }) - logger.info({ from, value }, `Processing transfer ${transfer.transactionHash}`) + logger.info('Processing transfer') const receipt = await config.foreign.web3.eth.getTransactionReceipt(transfer.transactionHash) - const existsAffirmationEvent = receipt.logs.some( - e => e.address === config.foreign.bridgeAddress && e.topics[0] === userRequestForAffirmationHash - ) - - if (existsAffirmationEvent) { - logger.info( - `Transfer event discarded because a transaction with alternative receiver detected in transaction ${ - transfer.transactionHash - }` - ) + if (receipt.logs.some(isUserRequestForAffirmation)) { + logger.info('Transfer event discarded because affirmation is detected in the same transaction') return } - const existsTokensSwappedEvent = tokensSwappedAbi - ? receipt.logs.some(e => e.address === config.foreign.bridgeAddress && e.topics[0] === tokensSwappedHash) - : false + if (from === ZERO_ADDRESS) { + logger.info('Mint-like transfers from zero address are not processed') + return + } - if (from === ZERO_ADDRESS && existsTokensSwappedEvent) { - logger.info( - `Transfer event discarded because token swap is detected in transaction ${transfer.transactionHash}` - ) + // when bridge performs a withdrawal from Compound, the following three events occur + // * token.Transfer(from=cToken, to=bridge, amount=X) + // * cToken.Redeem(redeemer=bridge, amount=X, tokens=Y) + // * cToken.Transfer(from=bridge, to=cToken, amount=Y) + if (receipt.logs.some(isRedeem(from)) && receipt.logs.some(isCTokenTransfer(from))) { + logger.info('Transfer event discarded because cToken redeem is detected in the same transaction') return } diff --git a/oracle/src/watcher.js b/oracle/src/watcher.js index 9be726ee..e0627042 100644 --- a/oracle/src/watcher.js +++ b/oracle/src/watcher.js @@ -156,8 +156,6 @@ async function main({ sendToQueue }) { logger.info(`Oracle watcher was unsuspended.`) } - await checkConditions() - const lastBlockToProcess = await getLastBlockToProcess(web3, bridgeContract) if (lastBlockToProcess <= lastProcessedBlock) { @@ -165,6 +163,8 @@ async function main({ sendToQueue }) { return } + await checkConditions() + const fromBlock = lastProcessedBlock + 1 const rangeEndBlock = config.blockPollingLimit ? fromBlock + config.blockPollingLimit : lastBlockToProcess let toBlock = Math.min(lastBlockToProcess, rangeEndBlock) diff --git a/parity/chain-foreign.json b/parity/chain-foreign.json index b05924fb..3e6fa5ca 100644 --- a/parity/chain-foreign.json +++ b/parity/chain-foreign.json @@ -91,7 +91,7 @@ }, "7FC1442AB55Da569940Eb750AaD2BAA63DA4010E": { "balance": "500000000000000000000" }, "B4579fd5AfEaB60B03Db3F408AAdD315035943f7": { "balance": "500000000000000000000" }, - "7cc4b1851c35959d34e635a470f6b5c43ba3c9c9": { + "6B175474E89094C44Da98b954EedeAC495271d0F": { "balance": "0", "code": "0x6080604052600436106100fb5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166305d2035b811461010057806306fdde0314610129578063095ea7b3146101b357806318160ddd146101d757806323b872dd146101fe578063313ce5671461022857806340c10f191461025357806342966c6814610277578063661884631461029157806370a08231146102b5578063715018a6146102d65780637d64bcb4146102eb5780638da5cb5b1461030057806395d89b4114610331578063a9059cbb14610346578063d73dd6231461036a578063dd62ed3e1461038e578063f2fde38b146103b5575b600080fd5b34801561010c57600080fd5b506101156103d6565b604080519115158252519081900360200190f35b34801561013557600080fd5b5061013e6103f7565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610178578181015183820152602001610160565b50505050905090810190601f1680156101a55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101bf57600080fd5b50610115600160a060020a0360043516602435610485565b3480156101e357600080fd5b506101ec6104eb565b60408051918252519081900360200190f35b34801561020a57600080fd5b50610115600160a060020a03600435811690602435166044356104f1565b34801561023457600080fd5b5061023d610656565b6040805160ff9092168252519081900360200190f35b34801561025f57600080fd5b50610115600160a060020a036004351660243561065f565b34801561028357600080fd5b5061028f60043561078a565b005b34801561029d57600080fd5b50610115600160a060020a0360043516602435610797565b3480156102c157600080fd5b506101ec600160a060020a0360043516610886565b3480156102e257600080fd5b5061028f6108a1565b3480156102f757600080fd5b5061011561090f565b34801561030c57600080fd5b506103156109b5565b60408051600160a060020a039092168252519081900360200190f35b34801561033d57600080fd5b5061013e6109c4565b34801561035257600080fd5b50610115600160a060020a0360043516602435610a1e565b34801561037657600080fd5b50610115600160a060020a0360043516602435610aed565b34801561039a57600080fd5b506101ec600160a060020a0360043581169060243516610b86565b3480156103c157600080fd5b5061028f600160a060020a0360043516610bb1565b60065474010000000000000000000000000000000000000000900460ff1681565b6000805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561047d5780601f106104525761010080835404028352916020019161047d565b820191906000526020600020905b81548152906001019060200180831161046057829003601f168201915b505050505081565b336000818152600560209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60045490565b600160a060020a03831660009081526003602052604081205482111561051657600080fd5b600160a060020a038416600090815260056020908152604080832033845290915290205482111561054657600080fd5b600160a060020a038316151561055b57600080fd5b600160a060020a038416600090815260036020526040902054610584908363ffffffff610bd116565b600160a060020a0380861660009081526003602052604080822093909355908516815220546105b9908363ffffffff610be316565b600160a060020a0380851660009081526003602090815260408083209490945591871681526005825282812033825290915220546105fd908363ffffffff610bd116565b600160a060020a0380861660008181526005602090815260408083203384528252918290209490945580518681529051928716939192600080516020610d64833981519152929181900390910190a35060019392505050565b60025460ff1681565b600654600090600160a060020a031633148061068e57507306af07097c9eeb7fd685c692751d5c66db49c21533145b151561069957600080fd5b60065474010000000000000000000000000000000000000000900460ff16156106c157600080fd5b6004546106d4908363ffffffff610be316565b600455600160a060020a038316600090815260036020526040902054610700908363ffffffff610be316565b600160a060020a038416600081815260036020908152604091829020939093558051858152905191927f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688592918290030190a2604080518381529051600160a060020a03851691600091600080516020610d648339815191529181900360200190a350600192915050565b6107943382610bf6565b50565b336000908152600560209081526040808320600160a060020a03861684529091528120548083106107eb57336000908152600560209081526040808320600160a060020a0388168452909152812055610820565b6107fb818463ffffffff610bd116565b336000908152600560209081526040808320600160a060020a03891684529091529020555b336000818152600560209081526040808320600160a060020a0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b600160a060020a031660009081526003602052604090205490565b600654600160a060020a031633146108b857600080fd5b600654604051600160a060020a03909116907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26006805473ffffffffffffffffffffffffffffffffffffffff19169055565b600654600090600160a060020a0316331461092957600080fd5b60065474010000000000000000000000000000000000000000900460ff161561095157600080fd5b6006805474ff00000000000000000000000000000000000000001916740100000000000000000000000000000000000000001790556040517fae5184fba832cb2b1f702aca6117b8d265eaf03ad33eb133f19dde0f5920fa0890600090a150600190565b600654600160a060020a031681565b60018054604080516020600284861615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561047d5780601f106104525761010080835404028352916020019161047d565b33600090815260036020526040812054821115610a3a57600080fd5b600160a060020a0383161515610a4f57600080fd5b33600090815260036020526040902054610a6f908363ffffffff610bd116565b3360009081526003602052604080822092909255600160a060020a03851681522054610aa1908363ffffffff610be316565b600160a060020a038416600081815260036020908152604091829020939093558051858152905191923392600080516020610d648339815191529281900390910190a350600192915050565b336000908152600560209081526040808320600160a060020a0386168452909152812054610b21908363ffffffff610be316565b336000818152600560209081526040808320600160a060020a0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b600160a060020a03918216600090815260056020908152604080832093909416825291909152205490565b600654600160a060020a03163314610bc857600080fd5b61079481610ce5565b600082821115610bdd57fe5b50900390565b81810182811015610bf057fe5b92915050565b600160a060020a038216600090815260036020526040902054811115610c1b57600080fd5b600160a060020a038216600090815260036020526040902054610c44908263ffffffff610bd116565b600160a060020a038316600090815260036020526040902055600454610c70908263ffffffff610bd116565b600455604080518281529051600160a060020a038416917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a2604080518281529051600091600160a060020a03851691600080516020610d648339815191529181900360200190a35050565b600160a060020a0381161515610cfa57600080fd5b600654604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790555600ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a723058202a7961c4a1262b1c97bda31945e4da4acd5a5180a88e8a2af25d1e7768b467610029", "storage": { @@ -104,6 +104,13 @@ "0xc19ddbb1e237d15aa362708548b7cbc089c94e4977af9e54c2f09f0ae28a35fc" : "0x0000000000000000000000000000000000000000000000056bc75e2d63100000", "0xca2b12ce800b15ade60b8e814bbbf66b91734af718ac5562e6b8adc9b4e5b629" : "0x0000000000000000000000000000000000000000000000056bc75e2d63100000" } + }, + "5d3a536E4D6DbD6114cc1Ead35777bAB948E3643": { + "balance": "0", + "code": "0x60806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063852a12e314610051578063a0712d6814610092575b600080fd5b34801561005d57600080fd5b5061007c600480360381019080803590602001909291905050506100d3565b6040518082815260200191505060405180910390f35b34801561009e57600080fd5b506100bd60048036038101908080359060200190929190505050610292565b6040518082815260200191505060405180910390f35b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561019957600080fd5b505af11580156101ad573d6000803e3d6000fd5b505050503073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a37fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a929338384604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a160009050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050600060405180830381600087803b15801561038c57600080fd5b505af11580156103a0573d6000803e3d6000fd5b505050507f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f338384604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001935050505060405180910390a13373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600090509190505600a165627a7a723058203f6b054ad169c1229c2ab0200bdc8f802e395623adca7c38b97a29114103c7800029", + "storage": { + "0x0": "0x6B175474E89094C44Da98b954EedeAC495271d0F" + } } } } diff --git a/parity/foreign_mocks/cDAIMock.sol b/parity/foreign_mocks/cDAIMock.sol new file mode 100644 index 00000000..c95a99c3 --- /dev/null +++ b/parity/foreign_mocks/cDAIMock.sol @@ -0,0 +1,33 @@ +pragma solidity 0.4.24; + +interface IERC20 { + function transferFrom(address from,address to,uint256 value) external; + function transfer(address to,uint256 value) external; +} + +contract cDaiMock { + IERC20 daiToken; + + event Transfer(address indexed from, address indexed to, uint amount); + event Mint(address minter, uint mintAmount, uint mintTokens); + event Redeem(address redeemer, uint redeemAmount, uint redeemTokens); + + + function mint(uint256 mintAmount) external returns (uint256) { + daiToken.transferFrom(msg.sender, address(this), mintAmount); + + emit Mint(msg.sender, mintAmount, mintAmount); + emit Transfer(address(this), msg.sender, mintAmount); + + return 0; + } + + function redeemUnderlying(uint256 redeemAmount) external returns (uint256) { + daiToken.transfer(msg.sender, redeemAmount); + + emit Transfer(msg.sender, address(this), redeemAmount); + emit Redeem(msg.sender, redeemAmount, redeemAmount); + + return 0; + } +}