212 lines
7.9 KiB
TypeScript
212 lines
7.9 KiB
TypeScript
import {
|
|
blockchainTests,
|
|
constants,
|
|
expect,
|
|
getRandomInteger,
|
|
randomAddress,
|
|
verifyEventsFromLogs,
|
|
} from '@0x/contracts-test-utils';
|
|
import { hexUtils, OwnableRevertErrors, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
|
|
|
|
import { artifacts } from './artifacts';
|
|
import { FlashWalletContract, TestCallTargetContract, TestCallTargetEvents } from './wrappers';
|
|
|
|
blockchainTests.resets('FlashWallet', env => {
|
|
let owner: string;
|
|
let wallet: FlashWalletContract;
|
|
let callTarget: TestCallTargetContract;
|
|
|
|
before(async () => {
|
|
[owner] = await env.getAccountAddressesAsync();
|
|
wallet = await FlashWalletContract.deployFrom0xArtifactAsync(
|
|
artifacts.FlashWallet,
|
|
env.provider,
|
|
{
|
|
...env.txDefaults,
|
|
from: owner,
|
|
},
|
|
artifacts,
|
|
);
|
|
callTarget = await TestCallTargetContract.deployFrom0xArtifactAsync(
|
|
artifacts.TestCallTarget,
|
|
env.provider,
|
|
env.txDefaults,
|
|
artifacts,
|
|
);
|
|
});
|
|
|
|
const TARGET_RETURN_VALUE = hexUtils.rightPad('0x12345678');
|
|
const REVERTING_DATA = '0x1337';
|
|
|
|
it('owned by deployer', () => {
|
|
return expect(wallet.owner().callAsync()).to.eventually.eq(owner);
|
|
});
|
|
|
|
describe('executeCall()', () => {
|
|
it('non-owner cannot call executeCall()', async () => {
|
|
const notOwner = randomAddress();
|
|
const tx = wallet
|
|
.executeCall(randomAddress(), hexUtils.random(), getRandomInteger(0, '100e18'))
|
|
.callAsync({ from: notOwner });
|
|
return expect(tx).to.revertWith(new OwnableRevertErrors.OnlyOwnerError(notOwner));
|
|
});
|
|
|
|
it('owner can call executeCall()', async () => {
|
|
const targetData = hexUtils.random(128);
|
|
const receipt = await wallet
|
|
.executeCall(callTarget.address, targetData, constants.ZERO_AMOUNT)
|
|
.awaitTransactionSuccessAsync({ from: owner });
|
|
verifyEventsFromLogs(
|
|
receipt.logs,
|
|
[
|
|
{
|
|
context: callTarget.address,
|
|
sender: wallet.address,
|
|
data: targetData,
|
|
value: constants.ZERO_AMOUNT,
|
|
},
|
|
],
|
|
TestCallTargetEvents.CallTargetCalled,
|
|
);
|
|
});
|
|
|
|
it('owner can call executeCall() with attached ETH', async () => {
|
|
const targetData = hexUtils.random(128);
|
|
const callValue = getRandomInteger(1, '1e18');
|
|
const receipt = await wallet
|
|
.executeCall(callTarget.address, targetData, callValue)
|
|
.awaitTransactionSuccessAsync({ from: owner, value: callValue });
|
|
verifyEventsFromLogs(
|
|
receipt.logs,
|
|
[
|
|
{
|
|
context: callTarget.address,
|
|
sender: wallet.address,
|
|
data: targetData,
|
|
value: callValue,
|
|
},
|
|
],
|
|
TestCallTargetEvents.CallTargetCalled,
|
|
);
|
|
});
|
|
|
|
it('owner can call executeCall() can transfer less ETH than attached', async () => {
|
|
const targetData = hexUtils.random(128);
|
|
const callValue = getRandomInteger(1, '1e18');
|
|
const receipt = await wallet
|
|
.executeCall(callTarget.address, targetData, callValue.minus(1))
|
|
.awaitTransactionSuccessAsync({ from: owner, value: callValue });
|
|
verifyEventsFromLogs(
|
|
receipt.logs,
|
|
[
|
|
{
|
|
context: callTarget.address,
|
|
sender: wallet.address,
|
|
data: targetData,
|
|
value: callValue.minus(1),
|
|
},
|
|
],
|
|
TestCallTargetEvents.CallTargetCalled,
|
|
);
|
|
});
|
|
|
|
it('wallet returns call result', async () => {
|
|
const result = await wallet
|
|
.executeCall(callTarget.address, hexUtils.random(128), constants.ZERO_AMOUNT)
|
|
.callAsync({ from: owner });
|
|
expect(result).to.eq(TARGET_RETURN_VALUE);
|
|
});
|
|
|
|
it('wallet wraps call revert', async () => {
|
|
const tx = wallet
|
|
.executeCall(callTarget.address, REVERTING_DATA, constants.ZERO_AMOUNT)
|
|
.callAsync({ from: owner });
|
|
return expect(tx).to.revertWith(
|
|
new ZeroExRevertErrors.Wallet.WalletExecuteCallFailedError(
|
|
wallet.address,
|
|
callTarget.address,
|
|
REVERTING_DATA,
|
|
constants.ZERO_AMOUNT,
|
|
new StringRevertError('TestCallTarget/REVERT'),
|
|
),
|
|
);
|
|
});
|
|
|
|
it('wallet can receive ETH', async () => {
|
|
await env.web3Wrapper.sendTransactionAsync({
|
|
to: wallet.address,
|
|
from: owner,
|
|
value: 1,
|
|
});
|
|
const bal = await env.web3Wrapper.getBalanceInWeiAsync(wallet.address);
|
|
expect(bal).to.bignumber.eq(1);
|
|
});
|
|
});
|
|
|
|
describe('executeDelegateCall()', () => {
|
|
it('non-owner cannot call executeDelegateCall()', async () => {
|
|
const notOwner = randomAddress();
|
|
const tx = wallet.executeDelegateCall(randomAddress(), hexUtils.random()).callAsync({ from: notOwner });
|
|
return expect(tx).to.revertWith(new OwnableRevertErrors.OnlyOwnerError(notOwner));
|
|
});
|
|
|
|
it('owner can call executeDelegateCall()', async () => {
|
|
const targetData = hexUtils.random(128);
|
|
const receipt = await wallet
|
|
.executeDelegateCall(callTarget.address, targetData)
|
|
.awaitTransactionSuccessAsync({ from: owner });
|
|
verifyEventsFromLogs(
|
|
receipt.logs,
|
|
[
|
|
{
|
|
context: wallet.address,
|
|
sender: owner,
|
|
data: targetData,
|
|
value: constants.ZERO_AMOUNT,
|
|
},
|
|
],
|
|
TestCallTargetEvents.CallTargetCalled,
|
|
);
|
|
});
|
|
|
|
it('executeDelegateCall() is payable', async () => {
|
|
const targetData = hexUtils.random(128);
|
|
const callValue = getRandomInteger(1, '1e18');
|
|
const receipt = await wallet
|
|
.executeDelegateCall(callTarget.address, targetData)
|
|
.awaitTransactionSuccessAsync({ from: owner, value: callValue });
|
|
verifyEventsFromLogs(
|
|
receipt.logs,
|
|
[
|
|
{
|
|
context: wallet.address,
|
|
sender: owner,
|
|
data: targetData,
|
|
value: callValue,
|
|
},
|
|
],
|
|
TestCallTargetEvents.CallTargetCalled,
|
|
);
|
|
});
|
|
|
|
it('wallet returns call result', async () => {
|
|
const result = await wallet
|
|
.executeDelegateCall(callTarget.address, hexUtils.random(128))
|
|
.callAsync({ from: owner });
|
|
expect(result).to.eq(TARGET_RETURN_VALUE);
|
|
});
|
|
|
|
it('wallet wraps call revert', async () => {
|
|
const tx = wallet.executeDelegateCall(callTarget.address, REVERTING_DATA).callAsync({ from: owner });
|
|
return expect(tx).to.revertWith(
|
|
new ZeroExRevertErrors.Wallet.WalletExecuteDelegateCallFailedError(
|
|
wallet.address,
|
|
callTarget.address,
|
|
REVERTING_DATA,
|
|
new StringRevertError('TestCallTarget/REVERT'),
|
|
),
|
|
);
|
|
});
|
|
});
|
|
});
|