protocol fee / staking integration tests (#40)
This commit is contained in:
parent
018e25345b
commit
b463a39bfa
@ -16,6 +16,7 @@
|
|||||||
"quotes": ["error", "double"],
|
"quotes": ["error", "double"],
|
||||||
"separate-by-one-line-in-contract": "error",
|
"separate-by-one-line-in-contract": "error",
|
||||||
"space-after-comma": "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": {
|
"config": {
|
||||||
"publicInterfaceContracts": "TestFramework",
|
"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."
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -12,12 +12,15 @@ import * as TestContractWrapper from '../test/generated-artifacts/TestContractWr
|
|||||||
import * as TestDydxUser from '../test/generated-artifacts/TestDydxUser.json';
|
import * as TestDydxUser from '../test/generated-artifacts/TestDydxUser.json';
|
||||||
import * as TestEth2Dai from '../test/generated-artifacts/TestEth2Dai.json';
|
import * as TestEth2Dai from '../test/generated-artifacts/TestEth2Dai.json';
|
||||||
import * as TestEth2DaiBridge from '../test/generated-artifacts/TestEth2DaiBridge.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 TestFramework from '../test/generated-artifacts/TestFramework.json';
|
||||||
import * as TestMainnetAggregatorFills from '../test/generated-artifacts/TestMainnetAggregatorFills.json';
|
import * as TestMainnetAggregatorFills from '../test/generated-artifacts/TestMainnetAggregatorFills.json';
|
||||||
import * as TestSignatureValidationWallet from '../test/generated-artifacts/TestSignatureValidationWallet.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 TestUniswapBridge from '../test/generated-artifacts/TestUniswapBridge.json';
|
||||||
import * as TestUniswapExchange from '../test/generated-artifacts/TestUniswapExchange.json';
|
import * as TestUniswapExchange from '../test/generated-artifacts/TestUniswapExchange.json';
|
||||||
import * as TestUniswapExchangeFactory from '../test/generated-artifacts/TestUniswapExchangeFactory.json';
|
import * as TestUniswapExchangeFactory from '../test/generated-artifacts/TestUniswapExchangeFactory.json';
|
||||||
|
import * as TestWethIntegration from '../test/generated-artifacts/TestWethIntegration.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
ChainlinkStopLimit: ChainlinkStopLimit as ContractArtifact,
|
ChainlinkStopLimit: ChainlinkStopLimit as ContractArtifact,
|
||||||
IChainlinkAggregator: IChainlinkAggregator as ContractArtifact,
|
IChainlinkAggregator: IChainlinkAggregator as ContractArtifact,
|
||||||
@ -26,10 +29,13 @@ export const artifacts = {
|
|||||||
TestDydxUser: TestDydxUser as ContractArtifact,
|
TestDydxUser: TestDydxUser as ContractArtifact,
|
||||||
TestEth2Dai: TestEth2Dai as ContractArtifact,
|
TestEth2Dai: TestEth2Dai as ContractArtifact,
|
||||||
TestEth2DaiBridge: TestEth2DaiBridge as ContractArtifact,
|
TestEth2DaiBridge: TestEth2DaiBridge as ContractArtifact,
|
||||||
|
TestFixinProtocolFeesIntegration: TestFixinProtocolFeesIntegration as ContractArtifact,
|
||||||
TestFramework: TestFramework as ContractArtifact,
|
TestFramework: TestFramework as ContractArtifact,
|
||||||
TestMainnetAggregatorFills: TestMainnetAggregatorFills as ContractArtifact,
|
TestMainnetAggregatorFills: TestMainnetAggregatorFills as ContractArtifact,
|
||||||
TestSignatureValidationWallet: TestSignatureValidationWallet as ContractArtifact,
|
TestSignatureValidationWallet: TestSignatureValidationWallet as ContractArtifact,
|
||||||
|
TestStaking: TestStaking as ContractArtifact,
|
||||||
TestUniswapBridge: TestUniswapBridge as ContractArtifact,
|
TestUniswapBridge: TestUniswapBridge as ContractArtifact,
|
||||||
TestUniswapExchange: TestUniswapExchange as ContractArtifact,
|
TestUniswapExchange: TestUniswapExchange as ContractArtifact,
|
||||||
TestUniswapExchangeFactory: TestUniswapExchangeFactory 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_dydx_user';
|
||||||
export * from '../test/generated-wrappers/test_eth2_dai';
|
export * from '../test/generated-wrappers/test_eth2_dai';
|
||||||
export * from '../test/generated-wrappers/test_eth2_dai_bridge';
|
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_framework';
|
||||||
export * from '../test/generated-wrappers/test_mainnet_aggregator_fills';
|
export * from '../test/generated-wrappers/test_mainnet_aggregator_fills';
|
||||||
export * from '../test/generated-wrappers/test_signature_validation_wallet';
|
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_bridge';
|
||||||
export * from '../test/generated-wrappers/test_uniswap_exchange';
|
export * from '../test/generated-wrappers/test_uniswap_exchange';
|
||||||
export * from '../test/generated-wrappers/test_uniswap_exchange_factory';
|
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/TestDydxUser.json",
|
||||||
"test/generated-artifacts/TestEth2Dai.json",
|
"test/generated-artifacts/TestEth2Dai.json",
|
||||||
"test/generated-artifacts/TestEth2DaiBridge.json",
|
"test/generated-artifacts/TestEth2DaiBridge.json",
|
||||||
|
"test/generated-artifacts/TestFixinProtocolFeesIntegration.json",
|
||||||
"test/generated-artifacts/TestFramework.json",
|
"test/generated-artifacts/TestFramework.json",
|
||||||
"test/generated-artifacts/TestMainnetAggregatorFills.json",
|
"test/generated-artifacts/TestMainnetAggregatorFills.json",
|
||||||
"test/generated-artifacts/TestSignatureValidationWallet.json",
|
"test/generated-artifacts/TestSignatureValidationWallet.json",
|
||||||
|
"test/generated-artifacts/TestStaking.json",
|
||||||
"test/generated-artifacts/TestUniswapBridge.json",
|
"test/generated-artifacts/TestUniswapBridge.json",
|
||||||
"test/generated-artifacts/TestUniswapExchange.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