Skip to content

Commit

Permalink
Merge pull request #26 from provable-things/test-re-entrancy-attack-i…
Browse files Browse the repository at this point in the history
…s-not-feasible

feat(tests): adds test checking that reentrancy attack is not possible during wETH withdrawal
  • Loading branch information
gskapka authored Oct 13, 2021
2 parents 8a64914 + 21735a0 commit b67cf06
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 1 deletion.
12 changes: 12 additions & 0 deletions contracts/CONTRACT_WITH_RE_ENTRANCY_ATTACK.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
pragma solidity ^0.6.0;

interface Erc20VaultInterface {
function setPNetwork(address _pnetwork) external;
}

contract CONTRACT_WITH_RE_ENTRANCY_ATTACK {
function attempReEntrancyAttack() payable public {
Erc20VaultInterface vaultContract = Erc20VaultInterface(msg.sender);
vaultContract.setPNetwork(address(this));
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ptokens-erc20-smart-contract",
"version": "1.13.0",
"version": "1.14.0",
"description": "The pToken ERC20 vault smart-contract",
"main": "index.js",
"scripts": {
Expand Down
28 changes: 28 additions & 0 deletions test/erc20-vault-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const ERC20_ARTIFACT = artifacts.require('ERC20_TOKEN')
const ERC777_ARTIFACT = artifacts.require('ERC777_TOKEN')
const VaultArtifact = artifacts.require('Erc20Vault')
const { expectRevert } = require('@openzeppelin/test-helpers')
const CONTRACT_WITH_RE_ENTRANCY_ATTACK_ARTIFACT = artifacts.require('CONTRACT_WITH_RE_ENTRANCY_ATTACK')
const CONTRACT_WITH_EXPENSIVE_FALLBACK_FXN_ARTIFACT = artifacts.require('CONTRACT_WITH_EXPENSIVE_FALLBACK_FXN')

const GAS_LIMIT = 3e6
Expand Down Expand Up @@ -567,4 +568,31 @@ contract('Erc20Vault', ([PNETWORK_ADDRESS, NON_PNETWORK_ADDRESS, TOKEN_HOLDER_AD
const pNetworkAfter = await VAULT_METHODS.PNETWORK().call()
assert.strictEqual(pNetworkAfter, pNetworkBefore)
})

it('Pegging out wETH Should not be susceptible to re-entrancy attack', async () => {
const calldata = web3.eth.abi.encodeFunctionCall({
name: 'attempReEntrancyAttack',
type: 'function',
inputs: [],
}, [])
const PEG_OUT_GAS_LIMIT = 450e3
const reEntrancyAttackContract = await getContract(web3, CONTRACT_WITH_RE_ENTRANCY_ATTACK_ARTIFACT)
const reEntrancyAttackContractAddress = reEntrancyAttackContract._address
await addTokenSupport(VAULT_METHODS, WETH_ADDRESS, PNETWORK_ADDRESS)
const reEntrancyAttackContractEthBalanceBeforePegout = await web3.eth.getBalance(reEntrancyAttackContractAddress)
assert.strictEqual(reEntrancyAttackContractEthBalanceBeforePegout, '0')
await VAULT_METHODS.pegInEth(DESTINATION_ADDRESS).send({ from: TOKEN_HOLDER_ADDRESS, value: TOKEN_AMOUNT })
const expectedError = 'ETH transfer failed when pegging out wETH!'
expectRevert(VAULT_METHODS['pegOut(address,address,uint256,bytes)'](
reEntrancyAttackContractAddress, WETH_ADDRESS, TOKEN_AMOUNT, calldata
)
.send({ from: PNETWORK_ADDRESS, gas: PEG_OUT_GAS_LIMIT }),
expectedError
)
assert.strictEqual(await WETH_CONTRACT.methods.balanceOf(VAULT_ADDRESS).call(), `${TOKEN_AMOUNT}`)
const reEntrancyAttackContractEthBalanceAfterPegout = await web3.eth.getBalance(reEntrancyAttackContractAddress)
assert.strictEqual(reEntrancyAttackContractEthBalanceAfterPegout, '0')
const vaultEthBalanceAfterPegOut = await web3.eth.getBalance(VAULT_ADDRESS)
assert.strictEqual(vaultEthBalanceAfterPegOut, '0', 'Vault\'s ETH balance after peg out must be 0!')
})
})

0 comments on commit b67cf06

Please sign in to comment.