protocol fee / staking integration tests (#40)
This commit is contained in:
parent
018e25345b
commit
b463a39bfa
@ -16,6 +16,7 @@
|
||||
"quotes": ["error", "double"],
|
||||
"separate-by-one-line-in-contract": "error",
|
||||
"space-after-comma": "error",
|
||||
"statement-indent": "error"
|
||||
"statement-indent": "error",
|
||||
"no-empty-blocks": false
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 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.6.5;
|
||||
|
||||
import "@0x/contracts-zero-ex/contracts/test/TestFixinProtocolFees.sol";
|
||||
|
||||
|
||||
contract TestFixinProtocolFeesIntegration is TestFixinProtocolFees {
|
||||
constructor(
|
||||
IEtherTokenV06 weth,
|
||||
IStaking staking,
|
||||
uint32 protocolFeeMultiplier
|
||||
)
|
||||
public
|
||||
TestFixinProtocolFees(weth, staking, protocolFeeMultiplier)
|
||||
{
|
||||
}
|
||||
}
|
110
contracts/integrations/contracts/test/TestStaking.sol
Normal file
110
contracts/integrations/contracts/test/TestStaking.sol
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
|
||||
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;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-staking/contracts/src/Staking.sol";
|
||||
|
||||
|
||||
contract TestStaking is
|
||||
Staking
|
||||
{
|
||||
IEtherToken public testWeth;
|
||||
|
||||
struct TestPool {
|
||||
uint96 operatorStake;
|
||||
uint96 membersStake;
|
||||
}
|
||||
|
||||
mapping(bytes32 => TestPool) private _testPools;
|
||||
|
||||
constructor(address exchangeAddress, IEtherToken _testWeth) public {
|
||||
testWeth = _testWeth;
|
||||
|
||||
_addAuthorizedAddress(msg.sender);
|
||||
init();
|
||||
validExchanges[exchangeAddress] = true;
|
||||
_removeAuthorizedAddressAtIndex(msg.sender, 0);
|
||||
}
|
||||
|
||||
function advanceEpoch()
|
||||
external
|
||||
{
|
||||
currentEpoch += 1;
|
||||
}
|
||||
|
||||
/// @dev Create a test pool.
|
||||
function createTestPool(
|
||||
bytes32 poolId,
|
||||
uint96 operatorStake,
|
||||
uint96 membersStake
|
||||
)
|
||||
external
|
||||
{
|
||||
TestPool storage pool = _testPools[poolId];
|
||||
pool.operatorStake = operatorStake;
|
||||
pool.membersStake = membersStake;
|
||||
}
|
||||
|
||||
function getAggregatedStatsForCurrentEpoch()
|
||||
external
|
||||
view
|
||||
returns (IStructs.AggregatedStats memory)
|
||||
{
|
||||
return aggregatedStatsByEpoch[currentEpoch];
|
||||
}
|
||||
|
||||
/// @dev Overridden to use test pools.
|
||||
function getTotalStakeDelegatedToPool(bytes32 poolId)
|
||||
public
|
||||
view
|
||||
returns (IStructs.StoredBalance memory balance)
|
||||
{
|
||||
TestPool memory pool = _testPools[poolId];
|
||||
uint96 stake = pool.operatorStake + pool.membersStake;
|
||||
return IStructs.StoredBalance({
|
||||
currentEpoch: currentEpoch.downcastToUint64(),
|
||||
currentEpochBalance: stake,
|
||||
nextEpochBalance: stake
|
||||
});
|
||||
}
|
||||
|
||||
/// @dev Overridden to use test pools.
|
||||
function getStakeDelegatedToPoolByOwner(address, bytes32 poolId)
|
||||
public
|
||||
view
|
||||
returns (IStructs.StoredBalance memory balance)
|
||||
{
|
||||
TestPool memory pool = _testPools[poolId];
|
||||
return IStructs.StoredBalance({
|
||||
currentEpoch: currentEpoch.downcastToUint64(),
|
||||
currentEpochBalance: pool.operatorStake,
|
||||
nextEpochBalance: pool.operatorStake
|
||||
});
|
||||
}
|
||||
|
||||
function getWethContract()
|
||||
public
|
||||
view
|
||||
returns (IEtherToken wethContract)
|
||||
{
|
||||
return testWeth;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 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.6.5;
|
||||
|
||||
import "@0x/contracts-zero-ex/contracts/test/TestWeth.sol";
|
||||
|
||||
|
||||
contract TestWethIntegration is TestWeth {}
|
@ -38,7 +38,7 @@
|
||||
},
|
||||
"config": {
|
||||
"publicInterfaceContracts": "TestFramework",
|
||||
"abis": "./test/generated-artifacts/@(ChainlinkStopLimit|IChainlinkAggregator|TestChainlinkAggregator|TestContractWrapper|TestDydxUser|TestEth2Dai|TestEth2DaiBridge|TestFramework|TestMainnetAggregatorFills|TestSignatureValidationWallet|TestUniswapBridge|TestUniswapExchange|TestUniswapExchangeFactory).json",
|
||||
"abis": "./test/generated-artifacts/@(ChainlinkStopLimit|IChainlinkAggregator|TestChainlinkAggregator|TestContractWrapper|TestDydxUser|TestEth2Dai|TestEth2DaiBridge|TestFixinProtocolFeesIntegration|TestFramework|TestMainnetAggregatorFills|TestSignatureValidationWallet|TestStaking|TestUniswapBridge|TestUniswapExchange|TestUniswapExchangeFactory|TestWethIntegration).json",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||
},
|
||||
"repository": {
|
||||
|
@ -12,12 +12,15 @@ import * as TestContractWrapper from '../test/generated-artifacts/TestContractWr
|
||||
import * as TestDydxUser from '../test/generated-artifacts/TestDydxUser.json';
|
||||
import * as TestEth2Dai from '../test/generated-artifacts/TestEth2Dai.json';
|
||||
import * as TestEth2DaiBridge from '../test/generated-artifacts/TestEth2DaiBridge.json';
|
||||
import * as TestFixinProtocolFeesIntegration from '../test/generated-artifacts/TestFixinProtocolFeesIntegration.json';
|
||||
import * as TestFramework from '../test/generated-artifacts/TestFramework.json';
|
||||
import * as TestMainnetAggregatorFills from '../test/generated-artifacts/TestMainnetAggregatorFills.json';
|
||||
import * as TestSignatureValidationWallet from '../test/generated-artifacts/TestSignatureValidationWallet.json';
|
||||
import * as TestStaking from '../test/generated-artifacts/TestStaking.json';
|
||||
import * as TestUniswapBridge from '../test/generated-artifacts/TestUniswapBridge.json';
|
||||
import * as TestUniswapExchange from '../test/generated-artifacts/TestUniswapExchange.json';
|
||||
import * as TestUniswapExchangeFactory from '../test/generated-artifacts/TestUniswapExchangeFactory.json';
|
||||
import * as TestWethIntegration from '../test/generated-artifacts/TestWethIntegration.json';
|
||||
export const artifacts = {
|
||||
ChainlinkStopLimit: ChainlinkStopLimit as ContractArtifact,
|
||||
IChainlinkAggregator: IChainlinkAggregator as ContractArtifact,
|
||||
@ -26,10 +29,13 @@ export const artifacts = {
|
||||
TestDydxUser: TestDydxUser as ContractArtifact,
|
||||
TestEth2Dai: TestEth2Dai as ContractArtifact,
|
||||
TestEth2DaiBridge: TestEth2DaiBridge as ContractArtifact,
|
||||
TestFixinProtocolFeesIntegration: TestFixinProtocolFeesIntegration as ContractArtifact,
|
||||
TestFramework: TestFramework as ContractArtifact,
|
||||
TestMainnetAggregatorFills: TestMainnetAggregatorFills as ContractArtifact,
|
||||
TestSignatureValidationWallet: TestSignatureValidationWallet as ContractArtifact,
|
||||
TestStaking: TestStaking as ContractArtifact,
|
||||
TestUniswapBridge: TestUniswapBridge as ContractArtifact,
|
||||
TestUniswapExchange: TestUniswapExchange as ContractArtifact,
|
||||
TestUniswapExchangeFactory: TestUniswapExchangeFactory as ContractArtifact,
|
||||
TestWethIntegration: TestWethIntegration as ContractArtifact,
|
||||
};
|
||||
|
@ -10,9 +10,12 @@ export * from '../test/generated-wrappers/test_contract_wrapper';
|
||||
export * from '../test/generated-wrappers/test_dydx_user';
|
||||
export * from '../test/generated-wrappers/test_eth2_dai';
|
||||
export * from '../test/generated-wrappers/test_eth2_dai_bridge';
|
||||
export * from '../test/generated-wrappers/test_fixin_protocol_fees_integration';
|
||||
export * from '../test/generated-wrappers/test_framework';
|
||||
export * from '../test/generated-wrappers/test_mainnet_aggregator_fills';
|
||||
export * from '../test/generated-wrappers/test_signature_validation_wallet';
|
||||
export * from '../test/generated-wrappers/test_staking';
|
||||
export * from '../test/generated-wrappers/test_uniswap_bridge';
|
||||
export * from '../test/generated-wrappers/test_uniswap_exchange';
|
||||
export * from '../test/generated-wrappers/test_uniswap_exchange_factory';
|
||||
export * from '../test/generated-wrappers/test_weth_integration';
|
||||
|
@ -0,0 +1,85 @@
|
||||
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
|
||||
import { BigNumber, hexUtils } from '@0x/utils';
|
||||
|
||||
import { artifacts } from '../artifacts';
|
||||
import {
|
||||
TestFixinProtocolFeesIntegrationContract,
|
||||
TestStakingContract,
|
||||
TestWethIntegrationContract,
|
||||
} from '../wrappers';
|
||||
|
||||
blockchainTests.resets('ProtocolFeeIntegration', env => {
|
||||
const FEE_MULTIPLIER = 70e3;
|
||||
let owner: string;
|
||||
let taker: string;
|
||||
let protocolFees: TestFixinProtocolFeesIntegrationContract;
|
||||
let staking: TestStakingContract;
|
||||
let weth: TestWethIntegrationContract;
|
||||
let singleFeeAmount: BigNumber;
|
||||
|
||||
before(async () => {
|
||||
[owner, taker] = await env.getAccountAddressesAsync();
|
||||
weth = await TestWethIntegrationContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestWethIntegration,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
staking = await TestStakingContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestStaking,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
constants.NULL_ADDRESS, // exchange address, which we don't know yet
|
||||
weth.address,
|
||||
);
|
||||
protocolFees = await TestFixinProtocolFeesIntegrationContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestFixinProtocolFeesIntegration,
|
||||
env.provider,
|
||||
{ ...env.txDefaults, from: taker },
|
||||
artifacts,
|
||||
weth.address,
|
||||
staking.address,
|
||||
FEE_MULTIPLIER,
|
||||
);
|
||||
await staking.addAuthorizedAddress(owner).awaitTransactionSuccessAsync();
|
||||
await staking.addExchangeAddress(protocolFees.address).awaitTransactionSuccessAsync({ from: owner });
|
||||
await weth.mint(taker, constants.ONE_ETHER).awaitTransactionSuccessAsync();
|
||||
await weth.approve(protocolFees.address, constants.ONE_ETHER).awaitTransactionSuccessAsync({ from: taker });
|
||||
|
||||
singleFeeAmount = await protocolFees.getSingleProtocolFee().callAsync();
|
||||
});
|
||||
|
||||
describe('fee collection integration', () => {
|
||||
const pool0 = constants.NULL_BYTES32;
|
||||
const poolId = hexUtils.random();
|
||||
|
||||
it('should collect fees for pool 0', async () => {
|
||||
await protocolFees.collectProtocolFee(pool0).awaitTransactionSuccessAsync({ value: singleFeeAmount });
|
||||
await protocolFees.transferFeesForPool(pool0).awaitTransactionSuccessAsync();
|
||||
|
||||
// Fees in the pool bytes32(0) don't get attributed to a pool.
|
||||
await expect(
|
||||
(await staking.getStakingPoolStatsThisEpoch(pool0).callAsync()).feesCollected,
|
||||
).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
|
||||
// Expected amount is singleFeeAmount - 1 because we leave 1 wei of WETH behind for future gas savings.
|
||||
return expect(await weth.balanceOf(staking.address).callAsync()).to.bignumber.equal(
|
||||
singleFeeAmount.minus(1),
|
||||
);
|
||||
});
|
||||
|
||||
it('should collect fees for non-zero pool', async () => {
|
||||
const eth100 = constants.ONE_ETHER.multipliedBy(100);
|
||||
await staking.createTestPool(poolId, eth100, eth100).awaitTransactionSuccessAsync();
|
||||
|
||||
await protocolFees.collectProtocolFee(poolId).awaitTransactionSuccessAsync({ value: singleFeeAmount });
|
||||
await protocolFees.transferFeesForPool(poolId).awaitTransactionSuccessAsync();
|
||||
|
||||
// Expected amount is singleFeeAmount - 1 because we leave 1 wei of WETH behind for future gas savings.
|
||||
return expect(
|
||||
(await staking.getStakingPoolStatsThisEpoch(poolId).callAsync()).feesCollected,
|
||||
).to.bignumber.equal(singleFeeAmount.minus(1));
|
||||
});
|
||||
});
|
||||
});
|
@ -11,11 +11,14 @@
|
||||
"test/generated-artifacts/TestDydxUser.json",
|
||||
"test/generated-artifacts/TestEth2Dai.json",
|
||||
"test/generated-artifacts/TestEth2DaiBridge.json",
|
||||
"test/generated-artifacts/TestFixinProtocolFeesIntegration.json",
|
||||
"test/generated-artifacts/TestFramework.json",
|
||||
"test/generated-artifacts/TestMainnetAggregatorFills.json",
|
||||
"test/generated-artifacts/TestSignatureValidationWallet.json",
|
||||
"test/generated-artifacts/TestStaking.json",
|
||||
"test/generated-artifacts/TestUniswapBridge.json",
|
||||
"test/generated-artifacts/TestUniswapExchange.json",
|
||||
"test/generated-artifacts/TestUniswapExchangeFactory.json"
|
||||
"test/generated-artifacts/TestUniswapExchangeFactory.json",
|
||||
"test/generated-artifacts/TestWethIntegration.json"
|
||||
]
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user