@0x:contracts-utils Added a Refundable contract
This commit is contained in:
36
contracts/utils/contracts/src/Refundable.sol
Normal file
36
contracts/utils/contracts/src/Refundable.sol
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
|
||||
contract Refundable {
|
||||
|
||||
// This bool is used by the refund modifier to allow for lazily evaluated refunds.
|
||||
bool internal shouldNotRefund;
|
||||
|
||||
modifier refund {
|
||||
if (shouldNotRefund) {
|
||||
_;
|
||||
} else {
|
||||
shouldNotRefund = true;
|
||||
_;
|
||||
msg.sender.transfer(address(this).balance);
|
||||
}
|
||||
}
|
||||
}
|
||||
66
contracts/utils/contracts/test/TestRefundable.sol
Normal file
66
contracts/utils/contracts/test/TestRefundable.sol
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
|
||||
import "../src/Refundable.sol";
|
||||
|
||||
|
||||
contract TestRefundable is
|
||||
Refundable
|
||||
{
|
||||
uint256 public counter = 2;
|
||||
|
||||
function setCounter(uint256 newCounter)
|
||||
external
|
||||
{
|
||||
counter = newCounter;
|
||||
}
|
||||
|
||||
function complexReentrantRefundFunction()
|
||||
external
|
||||
payable
|
||||
refund()
|
||||
{
|
||||
if (counter == 0) {
|
||||
// This call tests lazy evaluation across different functions with the refund modifier
|
||||
this.simpleRefundFunction();
|
||||
} else {
|
||||
counter--;
|
||||
this.complexReentrantRefundFunction();
|
||||
}
|
||||
}
|
||||
|
||||
function simpleReentrantRefundFunction()
|
||||
external
|
||||
payable
|
||||
refund()
|
||||
{
|
||||
if (counter != 0) {
|
||||
counter--;
|
||||
this.simpleReentrantRefundFunction();
|
||||
}
|
||||
}
|
||||
|
||||
function simpleRefundFunction()
|
||||
external
|
||||
payable
|
||||
refund()
|
||||
{} // solhint-disable-line no-empty-blocks
|
||||
|
||||
}
|
||||
@@ -35,7 +35,7 @@
|
||||
"compile:truffle": "truffle compile"
|
||||
},
|
||||
"config": {
|
||||
"abis": "./generated-artifacts/@(Authorizable|IAuthorizable|IOwnable|LibAddress|LibAddressArray|LibAddressArrayRichErrors|LibAuthorizableRichErrors|LibBytes|LibBytesRichErrors|LibEIP1271|LibEIP712|LibOwnableRichErrors|LibReentrancyGuardRichErrors|LibRichErrors|LibSafeMath|LibSafeMathRichErrors|Ownable|ReentrancyGuard|SafeMath|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibRichErrors|TestLogDecoding|TestLogDecodingDownstream|TestOwnable|TestReentrancyGuard|TestSafeMath).json",
|
||||
"abis": "./generated-artifacts/@(Authorizable|IAuthorizable|IOwnable|LibAddress|LibAddressArray|LibAddressArrayRichErrors|LibAuthorizableRichErrors|LibBytes|LibBytesRichErrors|LibEIP1271|LibEIP712|LibOwnableRichErrors|LibReentrancyGuardRichErrors|LibRichErrors|LibSafeMath|LibSafeMathRichErrors|Ownable|ReentrancyGuard|Refundable|SafeMath|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibRichErrors|TestLogDecoding|TestLogDecodingDownstream|TestOwnable|TestReentrancyGuard|TestRefundable|TestSafeMath).json",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||
},
|
||||
"repository": {
|
||||
|
||||
@@ -23,6 +23,7 @@ import * as LibSafeMath from '../generated-artifacts/LibSafeMath.json';
|
||||
import * as LibSafeMathRichErrors from '../generated-artifacts/LibSafeMathRichErrors.json';
|
||||
import * as Ownable from '../generated-artifacts/Ownable.json';
|
||||
import * as ReentrancyGuard from '../generated-artifacts/ReentrancyGuard.json';
|
||||
import * as Refundable from '../generated-artifacts/Refundable.json';
|
||||
import * as SafeMath from '../generated-artifacts/SafeMath.json';
|
||||
import * as TestLibAddress from '../generated-artifacts/TestLibAddress.json';
|
||||
import * as TestLibAddressArray from '../generated-artifacts/TestLibAddressArray.json';
|
||||
@@ -33,6 +34,7 @@ import * as TestLogDecoding from '../generated-artifacts/TestLogDecoding.json';
|
||||
import * as TestLogDecodingDownstream from '../generated-artifacts/TestLogDecodingDownstream.json';
|
||||
import * as TestOwnable from '../generated-artifacts/TestOwnable.json';
|
||||
import * as TestReentrancyGuard from '../generated-artifacts/TestReentrancyGuard.json';
|
||||
import * as TestRefundable from '../generated-artifacts/TestRefundable.json';
|
||||
import * as TestSafeMath from '../generated-artifacts/TestSafeMath.json';
|
||||
export const artifacts = {
|
||||
Authorizable: Authorizable as ContractArtifact,
|
||||
@@ -51,6 +53,7 @@ export const artifacts = {
|
||||
LibSafeMathRichErrors: LibSafeMathRichErrors as ContractArtifact,
|
||||
Ownable: Ownable as ContractArtifact,
|
||||
ReentrancyGuard: ReentrancyGuard as ContractArtifact,
|
||||
Refundable: Refundable as ContractArtifact,
|
||||
SafeMath: SafeMath as ContractArtifact,
|
||||
IAuthorizable: IAuthorizable as ContractArtifact,
|
||||
IOwnable: IOwnable as ContractArtifact,
|
||||
@@ -63,5 +66,6 @@ export const artifacts = {
|
||||
TestLogDecodingDownstream: TestLogDecodingDownstream as ContractArtifact,
|
||||
TestOwnable: TestOwnable as ContractArtifact,
|
||||
TestReentrancyGuard: TestReentrancyGuard as ContractArtifact,
|
||||
TestRefundable: TestRefundable as ContractArtifact,
|
||||
TestSafeMath: TestSafeMath as ContractArtifact,
|
||||
};
|
||||
|
||||
@@ -21,6 +21,7 @@ export * from '../generated-wrappers/lib_safe_math';
|
||||
export * from '../generated-wrappers/lib_safe_math_rich_errors';
|
||||
export * from '../generated-wrappers/ownable';
|
||||
export * from '../generated-wrappers/reentrancy_guard';
|
||||
export * from '../generated-wrappers/refundable';
|
||||
export * from '../generated-wrappers/safe_math';
|
||||
export * from '../generated-wrappers/test_lib_address';
|
||||
export * from '../generated-wrappers/test_lib_address_array';
|
||||
@@ -31,4 +32,5 @@ export * from '../generated-wrappers/test_log_decoding';
|
||||
export * from '../generated-wrappers/test_log_decoding_downstream';
|
||||
export * from '../generated-wrappers/test_ownable';
|
||||
export * from '../generated-wrappers/test_reentrancy_guard';
|
||||
export * from '../generated-wrappers/test_refundable';
|
||||
export * from '../generated-wrappers/test_safe_math';
|
||||
|
||||
85
contracts/utils/test/refundable.ts
Normal file
85
contracts/utils/test/refundable.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
import * as chai from 'chai';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { artifacts, TestRefundableContract } from '../src';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
describe('Refundable', () => {
|
||||
let owner: string;
|
||||
let notOwner: string;
|
||||
let address: string;
|
||||
let refundable: TestRefundableContract;
|
||||
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
before(async () => {
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
[owner, address, notOwner] = _.slice(accounts, 0, 3);
|
||||
refundable = await TestRefundableContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestRefundable,
|
||||
provider,
|
||||
txDefaults,
|
||||
{},
|
||||
);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
describe('refund', async () => {
|
||||
it('should refund all of the ether sent to the simpleRefundFunction', async () => {
|
||||
await expect(
|
||||
refundable.simpleRefundFunction.sendTransactionAsync({
|
||||
from: owner,
|
||||
value: Web3Wrapper.toBaseUnitAmount(1, 18),
|
||||
}),
|
||||
).to.be.fulfilled(''); // tslint:disable-line:await-promise
|
||||
expect(await web3Wrapper.getBalanceInWeiAsync(refundable.address)).bignumber.to.be.eq(
|
||||
constants.ZERO_AMOUNT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should refund all of the ether sent to the simpleReentrantRefundFunction with a counter of 2', async () => {
|
||||
await expect(
|
||||
refundable.simpleReentrantRefundFunction.sendTransactionAsync({
|
||||
from: owner,
|
||||
value: Web3Wrapper.toBaseUnitAmount(1, 18),
|
||||
}),
|
||||
).to.be.fulfilled(''); // tslint:disable-line:await-promise
|
||||
expect(await web3Wrapper.getBalanceInWeiAsync(refundable.address)).bignumber.to.be.eq(
|
||||
constants.ZERO_AMOUNT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should refund all of the ether sent to the complexReentrantRefundFunction with a counter of 2', async () => {
|
||||
await expect(
|
||||
refundable.complexReentrantRefundFunction.sendTransactionAsync({
|
||||
from: owner,
|
||||
value: Web3Wrapper.toBaseUnitAmount(1, 18),
|
||||
}),
|
||||
).to.be.fulfilled(''); // tslint:disable-line:await-promise
|
||||
expect(await web3Wrapper.getBalanceInWeiAsync(refundable.address)).bignumber.to.be.eq(
|
||||
constants.ZERO_AMOUNT,
|
||||
);
|
||||
});
|
||||
|
||||
// FIXME - Receiver tests
|
||||
});
|
||||
});
|
||||
@@ -21,6 +21,7 @@
|
||||
"generated-artifacts/LibSafeMathRichErrors.json",
|
||||
"generated-artifacts/Ownable.json",
|
||||
"generated-artifacts/ReentrancyGuard.json",
|
||||
"generated-artifacts/Refundable.json",
|
||||
"generated-artifacts/SafeMath.json",
|
||||
"generated-artifacts/TestLibAddress.json",
|
||||
"generated-artifacts/TestLibAddressArray.json",
|
||||
@@ -31,6 +32,7 @@
|
||||
"generated-artifacts/TestLogDecodingDownstream.json",
|
||||
"generated-artifacts/TestOwnable.json",
|
||||
"generated-artifacts/TestReentrancyGuard.json",
|
||||
"generated-artifacts/TestRefundable.json",
|
||||
"generated-artifacts/TestSafeMath.json"
|
||||
],
|
||||
"exclude": ["./deploy/solc/solc_bin"]
|
||||
|
||||
Reference in New Issue
Block a user