diff --git a/packages/contracts/src/core/dao/DAO.sol b/packages/contracts/src/core/dao/DAO.sol index 5258e474a..e4b1a39c7 100644 --- a/packages/contracts/src/core/dao/DAO.sol +++ b/packages/contracts/src/core/dao/DAO.sol @@ -77,9 +77,7 @@ contract DAO is error ActionFailed(uint256 index); /// @notice Thrown if an action has insufficent gas left. - /// @param limit The minimal gas that should be left. - /// @param actual The actual gas left. - error InsufficientGas(uint256 limit, uint256 actual); + error InsufficientGas(); /// @notice Thrown if the deposit amount is zero. error ZeroAmount(); @@ -207,9 +205,9 @@ contract DAO is uint256 gasAfter = gasleft(); if (!success) { - // This check prevents this actions to fail because of insufficient gas + // This check prevents this action to fail because of insufficient gas if (gasAfter < gasBefore / 64) { - revert InsufficientGas({limit: gasBefore / 64, actual: gasAfter}); + revert InsufficientGas(); } // Store that this specific action has actually failed. diff --git a/packages/contracts/src/test/dao/GasConsumerHelper.sol b/packages/contracts/src/test/dao/GasConsumerHelper.sol new file mode 100644 index 000000000..4dbbc62fc --- /dev/null +++ b/packages/contracts/src/test/dao/GasConsumerHelper.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later + +pragma solidity 0.8.17; + +contract GasConsumer { + mapping(uint256 => uint256) public store; + + function consumeGas(uint256 count) external { + for (uint i = 0; i < count; i++) { + store[i] = 1; + } + } +} diff --git a/packages/contracts/test/core/dao/dao.ts b/packages/contracts/test/core/dao/dao.ts index 1f4b9fdb7..ab53747b7 100644 --- a/packages/contracts/test/core/dao/dao.ts +++ b/packages/contracts/test/core/dao/dao.ts @@ -2,7 +2,14 @@ import chai, {expect} from 'chai'; import {ethers} from 'hardhat'; import {SignerWithAddress} from '@nomiclabs/hardhat-ethers/signers'; -import {DAO, TestERC1155, TestERC20, TestERC721} from '../../../typechain'; +import { + DAO, + TestERC1155, + TestERC20, + TestERC721, + IERC1271__factory, + GasConsumer__factory, +} from '../../../typechain'; import {findEvent, DAO_EVENTS} from '../../../utils/event'; import {flipBit} from '../../test-utils/bitmap'; @@ -16,7 +23,6 @@ import { import {getInterfaceID} from '../../test-utils/interfaces'; import {OZ_ERRORS} from '../../test-utils/error'; -import {IERC1271__factory} from '../../../typechain/factories/IERC1271__factory'; import {smock} from '@defi-wonderland/smock'; import {deployWithProxy} from '../../test-utils/proxy'; import {UNREGISTERED_INTERFACE_RETURN} from './callback-handler'; @@ -368,6 +374,33 @@ describe('DAO', function () { expect(event.args.execResults[0]).to.equal(data.successActionResult); }); + it('reverts if failure is allowed but not enough gas is provided', async () => { + const GasConsumer = new GasConsumer__factory(signers[0]); + let gasConsumer = await GasConsumer.deploy(); + + const gasConsumingAction = { + to: gasConsumer.address, + data: GasConsumer.interface.encodeFunctionData('consumeGas', [20]), + value: 0, + }; + const expectedGas = 495453; + + let allowFailureMap = ethers.BigNumber.from(0); + allowFailureMap = flipBit(0, allowFailureMap); // allow the action to fail + + await expect( + dao.execute(ZERO_BYTES32, [gasConsumingAction], allowFailureMap, { + gasLimit: expectedGas - 1, + }) + ).to.be.revertedWithCustomError(dao, 'InsufficientGas'); + + await expect( + dao.execute(ZERO_BYTES32, [gasConsumingAction], allowFailureMap, { + gasLimit: expectedGas, + }) + ).to.not.be.reverted; + }); + describe('Transfering tokens', async () => { const amount = ethers.utils.parseEther('1.23'); const options = {value: amount};