Compare commits
4 Commits
romain/tes
...
romain/sam
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f8a4101d5 | ||
|
|
15b7cf3986 | ||
|
|
5d4481f0f0 | ||
|
|
2a9871d706 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -75,9 +75,8 @@ generated_docs/
|
||||
|
||||
TODO.md
|
||||
|
||||
# IDE file
|
||||
# VSCode file
|
||||
.vscode
|
||||
.idea
|
||||
|
||||
# generated contract artifacts/
|
||||
contracts/broker/generated-artifacts/
|
||||
|
||||
@@ -1,22 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1631710679,
|
||||
"version": "3.3.20",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1631120757,
|
||||
"version": "3.3.19",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1630459879,
|
||||
"version": "3.3.18",
|
||||
|
||||
@@ -5,14 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v3.3.20 - _September 15, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.19 - _September 8, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.3.18 - _September 1, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-erc20",
|
||||
"version": "3.3.20",
|
||||
"version": "3.3.18",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -51,18 +51,18 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.6.2",
|
||||
"@0x/contracts-gen": "^2.0.40",
|
||||
"@0x/contracts-test-utils": "^5.4.11",
|
||||
"@0x/contracts-utils": "^4.8.1",
|
||||
"@0x/dev-utils": "^4.2.9",
|
||||
"@0x/sol-compiler": "^4.7.5",
|
||||
"@0x/abi-gen": "^5.6.0",
|
||||
"@0x/contracts-gen": "^2.0.38",
|
||||
"@0x/contracts-test-utils": "^5.4.10",
|
||||
"@0x/contracts-utils": "^4.7.18",
|
||||
"@0x/dev-utils": "^4.2.7",
|
||||
"@0x/sol-compiler": "^4.7.3",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.4",
|
||||
"@0x/types": "^3.3.4",
|
||||
"@0x/typescript-typings": "^5.2.1",
|
||||
"@0x/utils": "^6.4.4",
|
||||
"@0x/web3-wrapper": "^7.6.0",
|
||||
"@0x/types": "^3.3.3",
|
||||
"@0x/typescript-typings": "^5.2.0",
|
||||
"@0x/utils": "^6.4.3",
|
||||
"@0x/web3-wrapper": "^7.5.3",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "12.12.54",
|
||||
@@ -70,7 +70,7 @@
|
||||
"chai-as-promised": "^7.1.0",
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"ethereum-types": "^3.6.0",
|
||||
"ethereum-types": "^3.5.0",
|
||||
"lodash": "^4.17.11",
|
||||
"make-promises-safe": "^1.1.0",
|
||||
"mocha": "^6.2.0",
|
||||
@@ -82,7 +82,7 @@
|
||||
"typescript": "4.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.4.2",
|
||||
"@0x/base-contract": "^6.4.0",
|
||||
"ethers": "~4.0.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1631710679,
|
||||
"version": "5.4.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1630459879,
|
||||
"version": "5.4.10",
|
||||
|
||||
@@ -5,10 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v5.4.11 - _September 15, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v5.4.10 - _September 1, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-test-utils",
|
||||
"version": "5.4.11",
|
||||
"version": "5.4.10",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -34,7 +34,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/test-utils",
|
||||
"devDependencies": {
|
||||
"@0x/sol-compiler": "^4.7.5",
|
||||
"@0x/sol-compiler": "^4.7.3",
|
||||
"@0x/tslint-config": "^4.1.4",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
@@ -42,20 +42,20 @@
|
||||
"typescript": "4.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/assert": "^3.0.29",
|
||||
"@0x/base-contract": "^6.4.2",
|
||||
"@0x/assert": "^3.0.27",
|
||||
"@0x/base-contract": "^6.4.0",
|
||||
"@0x/contract-addresses": "^6.7.0",
|
||||
"@0x/dev-utils": "^4.2.9",
|
||||
"@0x/json-schemas": "^6.3.0",
|
||||
"@0x/dev-utils": "^4.2.7",
|
||||
"@0x/json-schemas": "^6.1.3",
|
||||
"@0x/order-utils": "^10.4.28",
|
||||
"@0x/sol-coverage": "^4.0.39",
|
||||
"@0x/sol-profiler": "^4.1.29",
|
||||
"@0x/sol-trace": "^3.0.39",
|
||||
"@0x/subproviders": "^6.6.0",
|
||||
"@0x/types": "^3.3.4",
|
||||
"@0x/typescript-typings": "^5.2.1",
|
||||
"@0x/utils": "^6.4.4",
|
||||
"@0x/web3-wrapper": "^7.6.0",
|
||||
"@0x/sol-coverage": "^4.0.37",
|
||||
"@0x/sol-profiler": "^4.1.27",
|
||||
"@0x/sol-trace": "^3.0.37",
|
||||
"@0x/subproviders": "^6.5.3",
|
||||
"@0x/types": "^3.3.3",
|
||||
"@0x/typescript-typings": "^5.2.0",
|
||||
"@0x/utils": "^6.4.3",
|
||||
"@0x/web3-wrapper": "^7.5.3",
|
||||
"@types/bn.js": "^4.11.0",
|
||||
"@types/js-combinatorics": "^0.5.29",
|
||||
"@types/lodash": "4.14.104",
|
||||
@@ -67,7 +67,7 @@
|
||||
"chai-bignumber": "^3.0.0",
|
||||
"decimal.js": "^10.2.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"ethereum-types": "^3.6.0",
|
||||
"ethereum-types": "^3.5.0",
|
||||
"ethereumjs-util": "^7.0.10",
|
||||
"ethers": "~4.0.4",
|
||||
"js-combinatorics": "^0.5.3",
|
||||
|
||||
@@ -1,22 +1,4 @@
|
||||
[
|
||||
{
|
||||
"version": "1.4.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Support cast vote by signature in Treasury"
|
||||
}
|
||||
],
|
||||
"timestamp": 1631710679
|
||||
},
|
||||
{
|
||||
"timestamp": 1631120757,
|
||||
"version": "1.3.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1630459879,
|
||||
"version": "1.3.4",
|
||||
|
||||
@@ -5,14 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.4.0 - _September 15, 2021_
|
||||
|
||||
* Support cast vote by signature in Treasury
|
||||
|
||||
## v1.3.5 - _September 8, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v1.3.4 - _September 1, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -136,9 +136,8 @@ interface IZrxTreasury {
|
||||
returns (uint256 proposalId);
|
||||
|
||||
/// @dev Casts a vote for the given proposal. Only callable
|
||||
/// during the voting period for that proposal.
|
||||
/// One address can only vote once.
|
||||
/// See `getVotingPower` for how voting power is computed.
|
||||
/// during the voting period for that proposal. See
|
||||
/// `getVotingPower` for how voting power is computed.
|
||||
/// @param proposalId The ID of the proposal to vote on.
|
||||
/// @param support Whether to support the proposal or not.
|
||||
/// @param operatedPoolIds The pools operated by `msg.sender`. The
|
||||
@@ -151,28 +150,6 @@ interface IZrxTreasury {
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Casts a vote for the given proposal, by signature.
|
||||
/// Only callable during the voting period for that proposal.
|
||||
/// One address/voter can only vote once.
|
||||
/// See `getVotingPower` for how voting power is computed.
|
||||
/// @param proposalId The ID of the proposal to vote on.
|
||||
/// @param support Whether to support the proposal or not.
|
||||
/// @param operatedPoolIds The pools operated by the signer. The
|
||||
/// ZRX currently delegated to those pools will be accounted
|
||||
/// for in the voting power.
|
||||
/// @param v the v field of the signature
|
||||
/// @param r the r field of the signature
|
||||
/// @param s the s field of the signature
|
||||
function castVoteBySignature(
|
||||
uint256 proposalId,
|
||||
bool support,
|
||||
bytes32[] memory operatedPoolIds,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
)
|
||||
external;
|
||||
|
||||
/// @dev Executes a proposal that has passed and is
|
||||
/// currently executable.
|
||||
/// @param proposalId The ID of the proposal to execute.
|
||||
|
||||
@@ -34,25 +34,11 @@ contract ZrxTreasury is
|
||||
using LibRichErrorsV06 for bytes;
|
||||
using LibBytesV06 for bytes;
|
||||
|
||||
/// Contract name
|
||||
string private constant CONTRACT_NAME = "Zrx Treasury";
|
||||
|
||||
/// Contract version
|
||||
string private constant CONTRACT_VERSION = "1.0.0";
|
||||
|
||||
/// The EIP-712 typehash for the contract's domain
|
||||
bytes32 private constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
|
||||
|
||||
/// The EIP-712 typehash for the vote struct
|
||||
bytes32 private constant VOTE_TYPEHASH = keccak256("TreasuryVote(uint256 proposalId,bool support,bytes32[] operatedPoolIds)");
|
||||
|
||||
// Immutables
|
||||
IStaking public immutable override stakingProxy;
|
||||
DefaultPoolOperator public immutable override defaultPoolOperator;
|
||||
bytes32 public immutable override defaultPoolId;
|
||||
uint256 public immutable override votingPeriod;
|
||||
bytes32 immutable domainSeparator;
|
||||
|
||||
uint256 public override proposalThreshold;
|
||||
uint256 public override quorumThreshold;
|
||||
|
||||
@@ -81,15 +67,6 @@ contract ZrxTreasury is
|
||||
defaultPoolId = params.defaultPoolId;
|
||||
IStaking.Pool memory defaultPool = stakingProxy_.getStakingPool(params.defaultPoolId);
|
||||
defaultPoolOperator = DefaultPoolOperator(defaultPool.operator);
|
||||
domainSeparator = keccak256(
|
||||
abi.encode(
|
||||
DOMAIN_TYPEHASH,
|
||||
keccak256(bytes(CONTRACT_NAME)),
|
||||
_getChainId(),
|
||||
keccak256(bytes(CONTRACT_VERSION)),
|
||||
address(this)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// solhint-disable
|
||||
@@ -128,7 +105,7 @@ contract ZrxTreasury is
|
||||
/// be executed if it passes. Must be at least two epochs
|
||||
/// from the current epoch.
|
||||
/// @param description A text description for the proposal.
|
||||
/// @param operatedPoolIds The pools operated by the signer. The
|
||||
/// @param operatedPoolIds The pools operated by `msg.sender`. The
|
||||
/// ZRX currently delegated to those pools will be accounted
|
||||
/// for in the voting power.
|
||||
/// @return proposalId The ID of the newly created proposal.
|
||||
@@ -173,9 +150,8 @@ contract ZrxTreasury is
|
||||
}
|
||||
|
||||
/// @dev Casts a vote for the given proposal. Only callable
|
||||
/// during the voting period for that proposal.
|
||||
/// One address can only vote once.
|
||||
/// See `getVotingPower` for how voting power is computed.
|
||||
/// during the voting period for that proposal. See
|
||||
/// `getVotingPower` for how voting power is computed.
|
||||
/// @param proposalId The ID of the proposal to vote on.
|
||||
/// @param support Whether to support the proposal or not.
|
||||
/// @param operatedPoolIds The pools operated by `msg.sender`. The
|
||||
@@ -189,39 +165,43 @@ contract ZrxTreasury is
|
||||
public
|
||||
override
|
||||
{
|
||||
return _castVote(msg.sender, proposalId, support, operatedPoolIds);
|
||||
if (proposalId >= proposalCount()) {
|
||||
revert("castVote/INVALID_PROPOSAL_ID");
|
||||
}
|
||||
if (hasVoted[proposalId][msg.sender]) {
|
||||
revert("castVote/ALREADY_VOTED");
|
||||
}
|
||||
|
||||
/// @dev Casts a vote for the given proposal, by signature.
|
||||
/// Only callable during the voting period for that proposal.
|
||||
/// One address/voter can only vote once.
|
||||
/// See `getVotingPower` for how voting power is computed.
|
||||
/// @param proposalId The ID of the proposal to vote on.
|
||||
/// @param support Whether to support the proposal or not.
|
||||
/// @param operatedPoolIds The pools operated by voter. The
|
||||
/// ZRX currently delegated to those pools will be accounted
|
||||
/// for in the voting power.
|
||||
/// @param v the v field of the signature
|
||||
/// @param r the r field of the signature
|
||||
/// @param s the s field of the signature
|
||||
function castVoteBySignature(
|
||||
uint256 proposalId,
|
||||
bool support,
|
||||
bytes32[] memory operatedPoolIds,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
)
|
||||
public
|
||||
override
|
||||
{
|
||||
bytes32 structHash = keccak256(
|
||||
abi.encode(VOTE_TYPEHASH, proposalId, support, keccak256(abi.encodePacked(operatedPoolIds)))
|
||||
);
|
||||
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
|
||||
address signatory = ecrecover(digest, v, r, s);
|
||||
Proposal memory proposal = proposals[proposalId];
|
||||
if (
|
||||
proposal.voteEpoch != stakingProxy.currentEpoch() ||
|
||||
_hasVoteEnded(proposal.voteEpoch)
|
||||
) {
|
||||
revert("castVote/VOTING_IS_CLOSED");
|
||||
}
|
||||
|
||||
return _castVote(signatory, proposalId, support, operatedPoolIds);
|
||||
uint256 votingPower = getVotingPower(msg.sender, operatedPoolIds);
|
||||
if (votingPower == 0) {
|
||||
revert("castVote/NO_VOTING_POWER");
|
||||
}
|
||||
|
||||
if (support) {
|
||||
proposals[proposalId].votesFor = proposals[proposalId].votesFor
|
||||
.safeAdd(votingPower);
|
||||
hasVoted[proposalId][msg.sender] = true;
|
||||
} else {
|
||||
proposals[proposalId].votesAgainst = proposals[proposalId].votesAgainst
|
||||
.safeAdd(votingPower);
|
||||
hasVoted[proposalId][msg.sender] = true;
|
||||
}
|
||||
|
||||
emit VoteCast(
|
||||
msg.sender,
|
||||
operatedPoolIds,
|
||||
proposalId,
|
||||
support,
|
||||
votingPower
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Executes a proposal that has passed and is
|
||||
@@ -393,60 +373,4 @@ contract ZrxTreasury is
|
||||
.safeAdd(votingPeriod);
|
||||
return block.timestamp > voteEndTime;
|
||||
}
|
||||
|
||||
/// @dev Casts a vote for the given proposal. Only callable
|
||||
/// during the voting period for that proposal. See
|
||||
/// `getVotingPower` for how voting power is computed.
|
||||
function _castVote(
|
||||
address voter,
|
||||
uint256 proposalId,
|
||||
bool support,
|
||||
bytes32[] memory operatedPoolIds
|
||||
)
|
||||
private
|
||||
{
|
||||
if (proposalId >= proposalCount()) {
|
||||
revert("_castVote/INVALID_PROPOSAL_ID");
|
||||
}
|
||||
if (hasVoted[proposalId][voter]) {
|
||||
revert("_castVote/ALREADY_VOTED");
|
||||
}
|
||||
|
||||
Proposal memory proposal = proposals[proposalId];
|
||||
if (
|
||||
proposal.voteEpoch != stakingProxy.currentEpoch() ||
|
||||
_hasVoteEnded(proposal.voteEpoch)
|
||||
) {
|
||||
revert("_castVote/VOTING_IS_CLOSED");
|
||||
}
|
||||
|
||||
uint256 votingPower = getVotingPower(voter, operatedPoolIds);
|
||||
if (votingPower == 0) {
|
||||
revert("_castVote/NO_VOTING_POWER");
|
||||
}
|
||||
|
||||
if (support) {
|
||||
proposals[proposalId].votesFor = proposals[proposalId].votesFor
|
||||
.safeAdd(votingPower);
|
||||
} else {
|
||||
proposals[proposalId].votesAgainst = proposals[proposalId].votesAgainst
|
||||
.safeAdd(votingPower);
|
||||
}
|
||||
hasVoted[proposalId][voter] = true;
|
||||
|
||||
emit VoteCast(
|
||||
voter,
|
||||
operatedPoolIds,
|
||||
proposalId,
|
||||
support,
|
||||
votingPower
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Gets the Ethereum chain id
|
||||
function _getChainId() private pure returns (uint256) {
|
||||
uint256 chainId;
|
||||
assembly { chainId := chainid() }
|
||||
return chainId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-treasury",
|
||||
"version": "1.4.0",
|
||||
"version": "1.3.4",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -46,14 +46,14 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.6.2",
|
||||
"@0x/abi-gen": "^5.6.0",
|
||||
"@0x/contract-addresses": "^6.7.0",
|
||||
"@0x/contracts-asset-proxy": "^3.7.19",
|
||||
"@0x/contracts-erc20": "^3.3.20",
|
||||
"@0x/contracts-gen": "^2.0.40",
|
||||
"@0x/contracts-erc20": "^3.3.18",
|
||||
"@0x/contracts-gen": "^2.0.38",
|
||||
"@0x/contracts-staking": "^2.0.45",
|
||||
"@0x/contracts-test-utils": "^5.4.11",
|
||||
"@0x/sol-compiler": "^4.7.5",
|
||||
"@0x/contracts-test-utils": "^5.4.10",
|
||||
"@0x/sol-compiler": "^4.7.3",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.4",
|
||||
"@types/isomorphic-fetch": "^0.0.35",
|
||||
@@ -72,14 +72,14 @@
|
||||
"typescript": "4.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.4.2",
|
||||
"@0x/protocol-utils": "^1.9.0",
|
||||
"@0x/subproviders": "^6.6.0",
|
||||
"@0x/types": "^3.3.4",
|
||||
"@0x/typescript-typings": "^5.2.1",
|
||||
"@0x/utils": "^6.4.4",
|
||||
"@0x/web3-wrapper": "^7.6.0",
|
||||
"ethereum-types": "^3.6.0",
|
||||
"@0x/base-contract": "^6.4.0",
|
||||
"@0x/protocol-utils": "^1.8.4",
|
||||
"@0x/subproviders": "^6.5.3",
|
||||
"@0x/types": "^3.3.3",
|
||||
"@0x/typescript-typings": "^5.2.0",
|
||||
"@0x/utils": "^6.4.3",
|
||||
"@0x/web3-wrapper": "^7.5.3",
|
||||
"ethereum-types": "^3.5.0",
|
||||
"ethereumjs-util": "^7.0.10"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
||||
@@ -17,9 +17,8 @@ import {
|
||||
randomAddress,
|
||||
verifyEventsFromLogs,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { TreasuryVote } from '@0x/protocol-utils';
|
||||
import { BigNumber, hexUtils } from '@0x/utils';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { artifacts } from './artifacts';
|
||||
import { DefaultPoolOperatorContract, ZrxTreasuryContract, ZrxTreasuryEvents } from './wrappers';
|
||||
@@ -56,8 +55,6 @@ blockchainTests.resets('Treasury governance', env => {
|
||||
let nonDefaultPoolId: string;
|
||||
let poolOperator: string;
|
||||
let delegator: string;
|
||||
let relayer: string;
|
||||
let delegatorPrivateKey: string;
|
||||
let actions: ProposedAction[];
|
||||
|
||||
async function deployStakingAsync(): Promise<void> {
|
||||
@@ -108,10 +105,7 @@ blockchainTests.resets('Treasury governance', env => {
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
const accounts = await env.getAccountAddressesAsync();
|
||||
[admin, poolOperator, delegator, relayer] = accounts;
|
||||
delegatorPrivateKey = hexUtils.toHex(constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(delegator)]);
|
||||
|
||||
[admin, poolOperator, delegator] = await env.getAccountAddressesAsync();
|
||||
zrx = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
erc20Artifacts.DummyERC20Token,
|
||||
env.provider,
|
||||
@@ -405,7 +399,7 @@ blockchainTests.resets('Treasury governance', env => {
|
||||
expect(await treasury.proposalCount().callAsync()).to.bignumber.equal(1);
|
||||
});
|
||||
});
|
||||
describe('castVote() and castVoteBySignature()', () => {
|
||||
describe('castVote()', () => {
|
||||
const VOTE_PROPOSAL_ID = new BigNumber(0);
|
||||
const DELEGATOR_VOTING_POWER = new BigNumber(420);
|
||||
|
||||
@@ -424,18 +418,17 @@ blockchainTests.resets('Treasury governance', env => {
|
||||
.propose(actions, currentEpoch.plus(2), PROPOSAL_DESCRIPTION, [])
|
||||
.awaitTransactionSuccessAsync({ from: delegator });
|
||||
});
|
||||
// castVote()
|
||||
it('Cannot vote on invalid proposalId', async () => {
|
||||
await fastForwardToNextEpochAsync();
|
||||
await fastForwardToNextEpochAsync();
|
||||
const tx = treasury
|
||||
.castVote(INVALID_PROPOSAL_ID, true, [])
|
||||
.awaitTransactionSuccessAsync({ from: delegator });
|
||||
return expect(tx).to.revertWith('_castVote/INVALID_PROPOSAL_ID');
|
||||
return expect(tx).to.revertWith('castVote/INVALID_PROPOSAL_ID');
|
||||
});
|
||||
it('Cannot vote before voting period starts', async () => {
|
||||
const tx = treasury.castVote(VOTE_PROPOSAL_ID, true, []).awaitTransactionSuccessAsync({ from: delegator });
|
||||
return expect(tx).to.revertWith('_castVote/VOTING_IS_CLOSED');
|
||||
return expect(tx).to.revertWith('castVote/VOTING_IS_CLOSED');
|
||||
});
|
||||
it('Cannot vote after voting period ends', async () => {
|
||||
await fastForwardToNextEpochAsync();
|
||||
@@ -443,14 +436,14 @@ blockchainTests.resets('Treasury governance', env => {
|
||||
await env.web3Wrapper.increaseTimeAsync(TREASURY_PARAMS.votingPeriod.plus(1).toNumber());
|
||||
await env.web3Wrapper.mineBlockAsync();
|
||||
const tx = treasury.castVote(VOTE_PROPOSAL_ID, true, []).awaitTransactionSuccessAsync({ from: delegator });
|
||||
return expect(tx).to.revertWith('_castVote/VOTING_IS_CLOSED');
|
||||
return expect(tx).to.revertWith('castVote/VOTING_IS_CLOSED');
|
||||
});
|
||||
it('Cannot vote twice on same proposal', async () => {
|
||||
await fastForwardToNextEpochAsync();
|
||||
await fastForwardToNextEpochAsync();
|
||||
await treasury.castVote(VOTE_PROPOSAL_ID, true, []).awaitTransactionSuccessAsync({ from: delegator });
|
||||
const tx = treasury.castVote(VOTE_PROPOSAL_ID, false, []).awaitTransactionSuccessAsync({ from: delegator });
|
||||
return expect(tx).to.revertWith('_castVote/ALREADY_VOTED');
|
||||
return expect(tx).to.revertWith('castVote/ALREADY_VOTED');
|
||||
});
|
||||
it('Can cast a valid vote', async () => {
|
||||
await fastForwardToNextEpochAsync();
|
||||
@@ -472,109 +465,6 @@ blockchainTests.resets('Treasury governance', env => {
|
||||
ZrxTreasuryEvents.VoteCast,
|
||||
);
|
||||
});
|
||||
// castVoteBySignature()
|
||||
it('Cannot vote by signature on invalid proposalId', async () => {
|
||||
await fastForwardToNextEpochAsync();
|
||||
await fastForwardToNextEpochAsync();
|
||||
const vote = new TreasuryVote({
|
||||
proposalId: INVALID_PROPOSAL_ID,
|
||||
verifyingContract: admin,
|
||||
});
|
||||
const signature = vote.getSignatureWithKey(delegatorPrivateKey);
|
||||
const tx = treasury
|
||||
.castVoteBySignature(INVALID_PROPOSAL_ID, true, [], signature.v, signature.r, signature.s)
|
||||
.awaitTransactionSuccessAsync({ from: relayer });
|
||||
return expect(tx).to.revertWith('_castVote/INVALID_PROPOSAL_ID');
|
||||
});
|
||||
it('Cannot vote by signature before voting period starts', async () => {
|
||||
const vote = new TreasuryVote({
|
||||
proposalId: VOTE_PROPOSAL_ID,
|
||||
verifyingContract: admin,
|
||||
});
|
||||
const signature = vote.getSignatureWithKey(delegatorPrivateKey);
|
||||
const tx = treasury
|
||||
.castVoteBySignature(VOTE_PROPOSAL_ID, true, [], signature.v, signature.r, signature.s)
|
||||
.awaitTransactionSuccessAsync({ from: relayer });
|
||||
return expect(tx).to.revertWith('_castVote/VOTING_IS_CLOSED');
|
||||
});
|
||||
it('Cannot vote by signature after voting period ends', async () => {
|
||||
await fastForwardToNextEpochAsync();
|
||||
await fastForwardToNextEpochAsync();
|
||||
await env.web3Wrapper.increaseTimeAsync(TREASURY_PARAMS.votingPeriod.plus(1).toNumber());
|
||||
await env.web3Wrapper.mineBlockAsync();
|
||||
|
||||
const vote = new TreasuryVote({
|
||||
proposalId: VOTE_PROPOSAL_ID,
|
||||
verifyingContract: admin,
|
||||
});
|
||||
const signature = vote.getSignatureWithKey(delegatorPrivateKey);
|
||||
const tx = treasury
|
||||
.castVoteBySignature(VOTE_PROPOSAL_ID, true, [], signature.v, signature.r, signature.s)
|
||||
.awaitTransactionSuccessAsync({ from: relayer });
|
||||
return expect(tx).to.revertWith('_castVote/VOTING_IS_CLOSED');
|
||||
});
|
||||
it('Can recover the address from signature correctly', async () => {
|
||||
const vote = new TreasuryVote({
|
||||
proposalId: VOTE_PROPOSAL_ID,
|
||||
verifyingContract: admin,
|
||||
});
|
||||
const signature = vote.getSignatureWithKey(delegatorPrivateKey);
|
||||
const publicKey = ethUtil.ecrecover(
|
||||
ethUtil.toBuffer(vote.getEIP712Hash()),
|
||||
signature.v,
|
||||
ethUtil.toBuffer(signature.r),
|
||||
ethUtil.toBuffer(signature.s),
|
||||
);
|
||||
const address = ethUtil.publicToAddress(publicKey);
|
||||
|
||||
expect(ethUtil.bufferToHex(address)).to.be.equal(delegator);
|
||||
});
|
||||
it('Can cast a valid vote by signature', async () => {
|
||||
await fastForwardToNextEpochAsync();
|
||||
await fastForwardToNextEpochAsync();
|
||||
|
||||
const vote = new TreasuryVote({
|
||||
proposalId: VOTE_PROPOSAL_ID,
|
||||
verifyingContract: treasury.address,
|
||||
chainId: 1337,
|
||||
support: false,
|
||||
});
|
||||
const signature = vote.getSignatureWithKey(delegatorPrivateKey);
|
||||
const tx = await treasury
|
||||
.castVoteBySignature(VOTE_PROPOSAL_ID, false, [], signature.v, signature.r, signature.s)
|
||||
.awaitTransactionSuccessAsync({ from: relayer });
|
||||
|
||||
verifyEventsFromLogs(
|
||||
tx.logs,
|
||||
[
|
||||
{
|
||||
voter: delegator,
|
||||
operatedPoolIds: [],
|
||||
proposalId: VOTE_PROPOSAL_ID,
|
||||
support: vote.support,
|
||||
votingPower: DELEGATOR_VOTING_POWER,
|
||||
},
|
||||
],
|
||||
ZrxTreasuryEvents.VoteCast,
|
||||
);
|
||||
});
|
||||
it('Cannot vote by signature twice on same proposal', async () => {
|
||||
await fastForwardToNextEpochAsync();
|
||||
await fastForwardToNextEpochAsync();
|
||||
await treasury.castVote(VOTE_PROPOSAL_ID, true, []).awaitTransactionSuccessAsync({ from: delegator });
|
||||
|
||||
const secondVote = new TreasuryVote({
|
||||
proposalId: VOTE_PROPOSAL_ID,
|
||||
verifyingContract: treasury.address,
|
||||
chainId: 1337,
|
||||
support: false,
|
||||
});
|
||||
const signature = secondVote.getSignatureWithKey(delegatorPrivateKey);
|
||||
const secondVoteTx = treasury
|
||||
.castVoteBySignature(VOTE_PROPOSAL_ID, false, [], signature.v, signature.r, signature.s)
|
||||
.awaitTransactionSuccessAsync({ from: relayer });
|
||||
return expect(secondVoteTx).to.revertWith('_castVote/ALREADY_VOTED');
|
||||
});
|
||||
});
|
||||
describe('execute()', () => {
|
||||
let passedProposalId: BigNumber;
|
||||
@@ -583,7 +473,7 @@ blockchainTests.resets('Treasury governance', env => {
|
||||
let ongoingVoteProposalId: BigNumber;
|
||||
|
||||
before(async () => {
|
||||
// Operator has enough ZRX to create and pass a proposal
|
||||
// OPerator has enough ZRX to create and pass a proposal
|
||||
await staking.stake(TREASURY_PARAMS.quorumThreshold).awaitTransactionSuccessAsync({ from: poolOperator });
|
||||
await staking
|
||||
.moveStake(
|
||||
@@ -659,7 +549,7 @@ blockchainTests.resets('Treasury governance', env => {
|
||||
});
|
||||
it('Cannot execute before or after the execution epoch', async () => {
|
||||
const tooEarly = treasury.execute(passedProposalId, actions).awaitTransactionSuccessAsync();
|
||||
await expect(tooEarly).to.revertWith('_assertProposalExecutable/CANNOT_EXECUTE_THIS_EPOCH');
|
||||
expect(tooEarly).to.revertWith('_assertProposalExecutable/CANNOT_EXECUTE_THIS_EPOCH');
|
||||
await fastForwardToNextEpochAsync();
|
||||
// Proposal 0 is executable here
|
||||
await fastForwardToNextEpochAsync();
|
||||
|
||||
@@ -1,23 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1631710679,
|
||||
"version": "4.8.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "4.8.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Added FundRecoveryFeature to the 0x EP",
|
||||
"pr": 306
|
||||
}
|
||||
],
|
||||
"timestamp": 1631120757
|
||||
},
|
||||
{
|
||||
"timestamp": 1630459879,
|
||||
"version": "4.7.18",
|
||||
|
||||
@@ -5,14 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v4.8.1 - _September 15, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v4.8.0 - _September 8, 2021_
|
||||
|
||||
* Added FundRecoveryFeature to the 0x EP (#306)
|
||||
|
||||
## v4.7.18 - _September 1, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-utils",
|
||||
"version": "4.8.1",
|
||||
"version": "4.7.18",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -50,15 +50,15 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/utils",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.6.2",
|
||||
"@0x/contracts-gen": "^2.0.40",
|
||||
"@0x/contracts-test-utils": "^5.4.11",
|
||||
"@0x/dev-utils": "^4.2.9",
|
||||
"@0x/abi-gen": "^5.6.0",
|
||||
"@0x/contracts-gen": "^2.0.38",
|
||||
"@0x/contracts-test-utils": "^5.4.10",
|
||||
"@0x/dev-utils": "^4.2.7",
|
||||
"@0x/order-utils": "^10.4.28",
|
||||
"@0x/sol-compiler": "^4.7.5",
|
||||
"@0x/sol-compiler": "^4.7.3",
|
||||
"@0x/tslint-config": "^4.1.4",
|
||||
"@0x/types": "^3.3.4",
|
||||
"@0x/web3-wrapper": "^7.6.0",
|
||||
"@0x/types": "^3.3.3",
|
||||
"@0x/web3-wrapper": "^7.5.3",
|
||||
"@types/bn.js": "^4.11.0",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^5.2.7",
|
||||
@@ -79,11 +79,11 @@
|
||||
"typescript": "4.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.4.2",
|
||||
"@0x/typescript-typings": "^5.2.1",
|
||||
"@0x/utils": "^6.4.4",
|
||||
"@0x/base-contract": "^6.4.0",
|
||||
"@0x/typescript-typings": "^5.2.0",
|
||||
"@0x/utils": "^6.4.3",
|
||||
"bn.js": "^4.11.8",
|
||||
"ethereum-types": "^3.6.0"
|
||||
"ethereum-types": "^3.5.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -1,22 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1631710679,
|
||||
"version": "0.28.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1631120757,
|
||||
"version": "0.28.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1630459879,
|
||||
"version": "0.28.3",
|
||||
|
||||
@@ -5,14 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v0.28.5 - _September 15, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.28.4 - _September 8, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v0.28.3 - _September 1, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -33,7 +33,6 @@ import "./features/interfaces/INativeOrdersFeature.sol";
|
||||
import "./features/interfaces/IBatchFillNativeOrdersFeature.sol";
|
||||
import "./features/interfaces/IMultiplexFeature.sol";
|
||||
import "./features/interfaces/IOtcOrdersFeature.sol";
|
||||
import "./features/interfaces/IFundRecoveryFeature.sol";
|
||||
|
||||
|
||||
/// @dev Interface for a fully featured Exchange Proxy.
|
||||
@@ -49,8 +48,7 @@ interface IZeroEx is
|
||||
INativeOrdersFeature,
|
||||
IBatchFillNativeOrdersFeature,
|
||||
IMultiplexFeature,
|
||||
IOtcOrdersFeature,
|
||||
IFundRecoveryFeature
|
||||
IOtcOrdersFeature
|
||||
{
|
||||
// solhint-disable state-visibility
|
||||
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright 2021 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;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||
import "../migrations/LibMigrate.sol";
|
||||
import "../fixins/FixinCommon.sol";
|
||||
import "./interfaces/IFeature.sol";
|
||||
import "./interfaces/IFundRecoveryFeature.sol";
|
||||
import "../transformers/LibERC20Transformer.sol";
|
||||
|
||||
contract FundRecoveryFeature is
|
||||
IFeature,
|
||||
IFundRecoveryFeature,
|
||||
FixinCommon
|
||||
{
|
||||
/// @dev Name of this feature.
|
||||
string public constant override FEATURE_NAME = "FundRecoveryFeature";
|
||||
/// @dev Version of this feature.
|
||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
|
||||
|
||||
/// @dev Initialize and register this feature.
|
||||
/// Should be delegatecalled by `Migrate.migrate()`.
|
||||
/// @return success `LibMigrate.SUCCESS` on success.
|
||||
function migrate()
|
||||
external
|
||||
returns (bytes4 success)
|
||||
{
|
||||
_registerFeatureFunction(this.transferTrappedTokensTo.selector);
|
||||
return LibMigrate.MIGRATE_SUCCESS;
|
||||
}
|
||||
|
||||
/// @dev Recovers ERC20 tokens or ETH from the 0x Exchange Proxy contract
|
||||
/// @param erc20 ERC20 Token Address. (You can also pass in `0xeeeee...` to indicate ETH)
|
||||
/// @param amountOut Amount of tokens to withdraw.
|
||||
/// @param recipientWallet Recipient wallet address.
|
||||
function transferTrappedTokensTo(
|
||||
IERC20TokenV06 erc20,
|
||||
uint256 amountOut,
|
||||
address payable recipientWallet
|
||||
)
|
||||
external
|
||||
override
|
||||
onlyOwner
|
||||
{
|
||||
if(amountOut == uint256(-1)) {
|
||||
amountOut = LibERC20Transformer.getTokenBalanceOf(erc20, address(this));
|
||||
}
|
||||
LibERC20Transformer.transformerTransfer(erc20, recipientWallet, amountOut);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
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;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||
|
||||
|
||||
/// @dev Exchange Proxy Recovery Functions
|
||||
interface IFundRecoveryFeature {
|
||||
|
||||
/// @dev calledFrom FundRecoveryFeature.transferTrappedTokensTo() This will be delegatecalled
|
||||
/// in the context of the Exchange Proxy instance being used.
|
||||
/// @param erc20 ERC20 Token Address.
|
||||
/// @param amountOut Amount of tokens to withdraw.
|
||||
/// @param recipientWallet Recipient wallet address.
|
||||
function transferTrappedTokensTo(
|
||||
IERC20TokenV06 erc20,
|
||||
uint256 amountOut,
|
||||
address payable recipientWallet
|
||||
)
|
||||
external;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contracts-zero-ex",
|
||||
"version": "0.28.5",
|
||||
"version": "0.28.3",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -43,7 +43,7 @@
|
||||
"config": {
|
||||
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature,OtcOrdersFeature,IOtcOrdersFeature",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|FundRecoveryFeature|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|IFundRecoveryFeature|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBalancerV2|MixinBancor|MixinClipper|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinKyber|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestMooniswap|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
||||
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBalancerV2|MixinBancor|MixinClipper|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinKyber|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|MultiplexLiquidityProvider|MultiplexOtc|MultiplexRfq|MultiplexTransformERC20|MultiplexUniswapV2|MultiplexUniswapV3|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OtcOrdersFeature|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestMooniswap|TestNativeOrdersFeature|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV2Factory|TestUniswapV2Pool|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -55,14 +55,14 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/contracts/zero-ex",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.6.2",
|
||||
"@0x/abi-gen": "^5.6.0",
|
||||
"@0x/contract-addresses": "^6.7.0",
|
||||
"@0x/contracts-erc20": "^3.3.20",
|
||||
"@0x/contracts-gen": "^2.0.40",
|
||||
"@0x/contracts-test-utils": "^5.4.11",
|
||||
"@0x/dev-utils": "^4.2.9",
|
||||
"@0x/contracts-erc20": "^3.3.18",
|
||||
"@0x/contracts-gen": "^2.0.38",
|
||||
"@0x/contracts-test-utils": "^5.4.10",
|
||||
"@0x/dev-utils": "^4.2.7",
|
||||
"@0x/order-utils": "^10.4.28",
|
||||
"@0x/sol-compiler": "^4.7.5",
|
||||
"@0x/sol-compiler": "^4.7.3",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.4",
|
||||
"@types/isomorphic-fetch": "^0.0.35",
|
||||
@@ -82,14 +82,14 @@
|
||||
"typescript": "4.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.4.2",
|
||||
"@0x/protocol-utils": "^1.9.0",
|
||||
"@0x/subproviders": "^6.6.0",
|
||||
"@0x/types": "^3.3.4",
|
||||
"@0x/typescript-typings": "^5.2.1",
|
||||
"@0x/utils": "^6.4.4",
|
||||
"@0x/web3-wrapper": "^7.6.0",
|
||||
"ethereum-types": "^3.6.0",
|
||||
"@0x/base-contract": "^6.4.0",
|
||||
"@0x/protocol-utils": "^1.8.4",
|
||||
"@0x/subproviders": "^6.5.3",
|
||||
"@0x/types": "^3.3.3",
|
||||
"@0x/typescript-typings": "^5.2.0",
|
||||
"@0x/utils": "^6.4.3",
|
||||
"@0x/web3-wrapper": "^7.5.3",
|
||||
"ethereum-types": "^3.5.0",
|
||||
"ethereumjs-util": "^7.0.10",
|
||||
"ethers": "~4.0.4"
|
||||
},
|
||||
|
||||
@@ -21,7 +21,6 @@ import * as FixinReentrancyGuard from '../test/generated-artifacts/FixinReentran
|
||||
import * as FixinTokenSpender from '../test/generated-artifacts/FixinTokenSpender.json';
|
||||
import * as FlashWallet from '../test/generated-artifacts/FlashWallet.json';
|
||||
import * as FullMigration from '../test/generated-artifacts/FullMigration.json';
|
||||
import * as FundRecoveryFeature from '../test/generated-artifacts/FundRecoveryFeature.json';
|
||||
import * as IBatchFillNativeOrdersFeature from '../test/generated-artifacts/IBatchFillNativeOrdersFeature.json';
|
||||
import * as IBootstrapFeature from '../test/generated-artifacts/IBootstrapFeature.json';
|
||||
import * as IBridgeAdapter from '../test/generated-artifacts/IBridgeAdapter.json';
|
||||
@@ -29,7 +28,6 @@ import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json';
|
||||
import * as IERC20Transformer from '../test/generated-artifacts/IERC20Transformer.json';
|
||||
import * as IFeature from '../test/generated-artifacts/IFeature.json';
|
||||
import * as IFlashWallet from '../test/generated-artifacts/IFlashWallet.json';
|
||||
import * as IFundRecoveryFeature from '../test/generated-artifacts/IFundRecoveryFeature.json';
|
||||
import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvider.json';
|
||||
import * as ILiquidityProviderFeature from '../test/generated-artifacts/ILiquidityProviderFeature.json';
|
||||
import * as ILiquidityProviderSandbox from '../test/generated-artifacts/ILiquidityProviderSandbox.json';
|
||||
@@ -200,7 +198,6 @@ export const artifacts = {
|
||||
TransformerDeployer: TransformerDeployer as ContractArtifact,
|
||||
BatchFillNativeOrdersFeature: BatchFillNativeOrdersFeature as ContractArtifact,
|
||||
BootstrapFeature: BootstrapFeature as ContractArtifact,
|
||||
FundRecoveryFeature: FundRecoveryFeature as ContractArtifact,
|
||||
LiquidityProviderFeature: LiquidityProviderFeature as ContractArtifact,
|
||||
MetaTransactionsFeature: MetaTransactionsFeature as ContractArtifact,
|
||||
NativeOrdersFeature: NativeOrdersFeature as ContractArtifact,
|
||||
@@ -214,7 +211,6 @@ export const artifacts = {
|
||||
IBatchFillNativeOrdersFeature: IBatchFillNativeOrdersFeature as ContractArtifact,
|
||||
IBootstrapFeature: IBootstrapFeature as ContractArtifact,
|
||||
IFeature: IFeature as ContractArtifact,
|
||||
IFundRecoveryFeature: IFundRecoveryFeature as ContractArtifact,
|
||||
ILiquidityProviderFeature: ILiquidityProviderFeature as ContractArtifact,
|
||||
IMetaTransactionsFeature: IMetaTransactionsFeature as ContractArtifact,
|
||||
IMultiplexFeature: IMultiplexFeature as ContractArtifact,
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
import { blockchainTests, constants, expect, randomAddress } from '@0x/contracts-test-utils';
|
||||
import { BigNumber, OwnableRevertErrors } from '@0x/utils';
|
||||
import { Web3Wrapper } from '@0x/web3-wrapper';
|
||||
|
||||
import { IOwnableFeatureContract, IZeroExContract } from '../../src/wrappers';
|
||||
import { artifacts } from '../artifacts';
|
||||
import { FundRecoveryFeatureContract } from '../generated-wrappers/fund_recovery_feature';
|
||||
import { abis } from '../utils/abis';
|
||||
import { fullMigrateAsync } from '../utils/migration';
|
||||
import { TestMintableERC20TokenContract } from '../wrappers';
|
||||
|
||||
blockchainTests('FundRecovery', async env => {
|
||||
let owner: string;
|
||||
let zeroEx: IZeroExContract;
|
||||
let token: TestMintableERC20TokenContract;
|
||||
before(async () => {
|
||||
const INITIAL_ERC20_BALANCE = Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18);
|
||||
[owner] = await env.getAccountAddressesAsync();
|
||||
zeroEx = await fullMigrateAsync(owner, env.provider, env.txDefaults, {});
|
||||
token = await TestMintableERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestMintableERC20Token,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
{},
|
||||
);
|
||||
await token.mint(zeroEx.address, INITIAL_ERC20_BALANCE).awaitTransactionSuccessAsync();
|
||||
const featureImpl = await FundRecoveryFeatureContract.deployFrom0xArtifactAsync(
|
||||
artifacts.FundRecoveryFeature,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
await new IOwnableFeatureContract(zeroEx.address, env.provider, env.txDefaults, abis)
|
||||
.migrate(featureImpl.address, featureImpl.migrate().getABIEncodedTransactionData(), owner)
|
||||
.awaitTransactionSuccessAsync({ from: owner });
|
||||
});
|
||||
blockchainTests.resets('Should delegatecall `transferTrappedTokensTo` from the exchange proxy', () => {
|
||||
const ETH_TOKEN_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
|
||||
const recipientAddress = randomAddress();
|
||||
it('Tranfers an arbitrary ERC-20 Token', async () => {
|
||||
const amountOut = Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18);
|
||||
await zeroEx
|
||||
.transferTrappedTokensTo(token.address, amountOut, recipientAddress)
|
||||
.awaitTransactionSuccessAsync({ from: owner });
|
||||
const recipientAddressBalanceAferTransfer = await token.balanceOf(recipientAddress).callAsync();
|
||||
return expect(recipientAddressBalanceAferTransfer).to.bignumber.equal(amountOut);
|
||||
});
|
||||
it('Amount -1 transfers entire balance of ERC-20', async () => {
|
||||
const balanceOwner = await token.balanceOf(zeroEx.address).callAsync();
|
||||
await zeroEx
|
||||
.transferTrappedTokensTo(token.address, constants.MAX_UINT256, recipientAddress)
|
||||
.awaitTransactionSuccessAsync({ from: owner });
|
||||
const recipientAddressBalanceAferTransfer = await token.balanceOf(recipientAddress).callAsync();
|
||||
return expect(recipientAddressBalanceAferTransfer).to.bignumber.equal(balanceOwner);
|
||||
});
|
||||
it('Amount -1 transfers entire balance of ETH', async () => {
|
||||
const amountOut = new BigNumber(20);
|
||||
await env.web3Wrapper.awaitTransactionMinedAsync(
|
||||
await env.web3Wrapper.sendTransactionAsync({
|
||||
from: owner,
|
||||
to: zeroEx.address,
|
||||
value: amountOut,
|
||||
}),
|
||||
);
|
||||
const balanceOwner = await env.web3Wrapper.getBalanceInWeiAsync(zeroEx.address);
|
||||
await zeroEx
|
||||
.transferTrappedTokensTo(ETH_TOKEN_ADDRESS, constants.MAX_UINT256, recipientAddress)
|
||||
.awaitTransactionSuccessAsync({ from: owner });
|
||||
const recipientAddressBalanceAferTransfer = await env.web3Wrapper.getBalanceInWeiAsync(recipientAddress);
|
||||
return expect(recipientAddressBalanceAferTransfer).to.bignumber.equal(balanceOwner);
|
||||
});
|
||||
it('Transfers ETH ', async () => {
|
||||
const amountOut = new BigNumber(20);
|
||||
await env.web3Wrapper.awaitTransactionMinedAsync(
|
||||
await env.web3Wrapper.sendTransactionAsync({
|
||||
from: owner,
|
||||
to: zeroEx.address,
|
||||
value: amountOut,
|
||||
}),
|
||||
);
|
||||
await zeroEx
|
||||
.transferTrappedTokensTo(ETH_TOKEN_ADDRESS, amountOut.minus(1), recipientAddress)
|
||||
.awaitTransactionSuccessAsync({ from: owner });
|
||||
const recipientAddressBalance = await env.web3Wrapper.getBalanceInWeiAsync(recipientAddress);
|
||||
return expect(recipientAddressBalance).to.bignumber.be.equal(amountOut.minus(1));
|
||||
});
|
||||
it('Feature `transferTrappedTokensTo` can only be called by owner', async () => {
|
||||
const notOwner = randomAddress();
|
||||
return expect(
|
||||
zeroEx
|
||||
.transferTrappedTokensTo(ETH_TOKEN_ADDRESS, constants.MAX_UINT256, recipientAddress)
|
||||
.awaitTransactionSuccessAsync({ from: notOwner }),
|
||||
).to.revertWith(new OwnableRevertErrors.OnlyOwnerError(notOwner, owner));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -19,7 +19,6 @@ export * from '../test/generated-wrappers/fixin_reentrancy_guard';
|
||||
export * from '../test/generated-wrappers/fixin_token_spender';
|
||||
export * from '../test/generated-wrappers/flash_wallet';
|
||||
export * from '../test/generated-wrappers/full_migration';
|
||||
export * from '../test/generated-wrappers/fund_recovery_feature';
|
||||
export * from '../test/generated-wrappers/i_batch_fill_native_orders_feature';
|
||||
export * from '../test/generated-wrappers/i_bootstrap_feature';
|
||||
export * from '../test/generated-wrappers/i_bridge_adapter';
|
||||
@@ -27,7 +26,6 @@ export * from '../test/generated-wrappers/i_erc20_bridge';
|
||||
export * from '../test/generated-wrappers/i_erc20_transformer';
|
||||
export * from '../test/generated-wrappers/i_feature';
|
||||
export * from '../test/generated-wrappers/i_flash_wallet';
|
||||
export * from '../test/generated-wrappers/i_fund_recovery_feature';
|
||||
export * from '../test/generated-wrappers/i_liquidity_provider';
|
||||
export * from '../test/generated-wrappers/i_liquidity_provider_feature';
|
||||
export * from '../test/generated-wrappers/i_liquidity_provider_sandbox';
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
"test/generated-artifacts/FixinTokenSpender.json",
|
||||
"test/generated-artifacts/FlashWallet.json",
|
||||
"test/generated-artifacts/FullMigration.json",
|
||||
"test/generated-artifacts/FundRecoveryFeature.json",
|
||||
"test/generated-artifacts/IBatchFillNativeOrdersFeature.json",
|
||||
"test/generated-artifacts/IBootstrapFeature.json",
|
||||
"test/generated-artifacts/IBridgeAdapter.json",
|
||||
@@ -60,7 +59,6 @@
|
||||
"test/generated-artifacts/IERC20Transformer.json",
|
||||
"test/generated-artifacts/IFeature.json",
|
||||
"test/generated-artifacts/IFlashWallet.json",
|
||||
"test/generated-artifacts/IFundRecoveryFeature.json",
|
||||
"test/generated-artifacts/ILiquidityProvider.json",
|
||||
"test/generated-artifacts/ILiquidityProviderFeature.json",
|
||||
"test/generated-artifacts/ILiquidityProviderSandbox.json",
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
six
|
||||
sphinx==3.5.4
|
||||
sphinx-markdown-tables
|
||||
@@ -46,7 +46,7 @@
|
||||
"test:generate_docs:circleci": "for i in ${npm_package_config_packagesWithDocPages}; do yarn generate_doc --package $i || break -1; done;",
|
||||
"bundlewatch": "bundlewatch",
|
||||
"lint": "wsrun --fast-exit --parallel --exclude-missing -p $PKG -c lint",
|
||||
"upgrade_org_deps": "node node_modules/@0x/monorepo-scripts/lib/upgrade_deps.js -p '@0x/|ethereum-types'",
|
||||
"upgrade_org_deps": "node node_modules/@0x/monorepo-scripts/lib/upgrade_deps.js -p '@0x|ethereum-types'",
|
||||
"upgrade_deps": "node node_modules/@0x/monorepo-scripts/lib/upgrade_deps.js",
|
||||
"verdaccio": "docker run --rm -i -p 4873:4873 0xorg/verdaccio"
|
||||
},
|
||||
|
||||
@@ -1,41 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1631710679,
|
||||
"version": "16.27.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1631646242,
|
||||
"version": "16.27.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1631639620,
|
||||
"version": "16.27.2",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "16.27.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Fix ApproximateBuys sampler to terminate if the buy amount is not met",
|
||||
"pr": 319
|
||||
}
|
||||
],
|
||||
"timestamp": 1631120757
|
||||
},
|
||||
{
|
||||
"version": "16.27.0",
|
||||
"changes": [
|
||||
|
||||
@@ -5,22 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v16.27.4 - _September 15, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v16.27.3 - _September 14, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v16.27.2 - _September 14, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v16.27.1 - _September 8, 2021_
|
||||
|
||||
* Fix ApproximateBuys sampler to terminate if the buy amount is not met (#319)
|
||||
|
||||
## v16.27.0 - _September 1, 2021_
|
||||
|
||||
* Avalanche deployment (#312)
|
||||
|
||||
@@ -77,7 +77,6 @@ contract ApproximateBuys {
|
||||
}
|
||||
|
||||
for (uint256 i = 0; i < makerTokenAmounts.length; i++) {
|
||||
uint256 eps = 0;
|
||||
for (uint256 iter = 0; iter < APPROXIMATE_BUY_MAX_ITERATIONS; iter++) {
|
||||
// adjustedSellAmount = previousSellAmount * (target/actual) * JUMP_MULTIPLIER
|
||||
sellAmount = _safeGetPartialAmountCeil(
|
||||
@@ -109,7 +108,7 @@ contract ApproximateBuys {
|
||||
buyAmount = _buyAmount;
|
||||
// If we've reached our goal, exit early
|
||||
if (buyAmount >= makerTokenAmounts[i]) {
|
||||
eps =
|
||||
uint256 eps =
|
||||
(buyAmount - makerTokenAmounts[i]) * ONE_HUNDED_PERCENT_BPS /
|
||||
makerTokenAmounts[i];
|
||||
if (eps <= APPROXIMATE_BUY_TARGET_EPSILON_BPS) {
|
||||
@@ -117,9 +116,6 @@ contract ApproximateBuys {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (eps == 0 || eps > APPROXIMATE_BUY_TARGET_EPSILON_BPS) {
|
||||
break;
|
||||
}
|
||||
// We do our best to close in on the requested amount, but we can either over buy or under buy and exit
|
||||
// if we hit a max iteration limit
|
||||
// We scale the sell amount to get the approximate target
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/asset-swapper",
|
||||
"version": "16.27.4",
|
||||
"version": "16.27.0",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -58,20 +58,20 @@
|
||||
"registry": "git@github.com:0xProject/gitpkg-registry.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/assert": "^3.0.29",
|
||||
"@0x/base-contract": "^6.4.2",
|
||||
"@0x/assert": "^3.0.27",
|
||||
"@0x/base-contract": "^6.4.0",
|
||||
"@0x/contract-addresses": "^6.7.0",
|
||||
"@0x/contract-wrappers": "^13.17.7",
|
||||
"@0x/contracts-erc20": "^3.3.20",
|
||||
"@0x/contracts-zero-ex": "^0.27.1",
|
||||
"@0x/dev-utils": "^4.2.9",
|
||||
"@0x/json-schemas": "^6.3.0",
|
||||
"@0x/protocol-utils": "^1.9.0",
|
||||
"@0x/quote-server": "^6.0.6",
|
||||
"@0x/types": "^3.3.4",
|
||||
"@0x/typescript-typings": "^5.2.1",
|
||||
"@0x/utils": "^6.4.4",
|
||||
"@0x/web3-wrapper": "^7.6.0",
|
||||
"@0x/contract-wrappers": "^13.17.6",
|
||||
"@0x/contracts-erc20": "^3.3.18",
|
||||
"@0x/contracts-zero-ex": "^0.27.0",
|
||||
"@0x/dev-utils": "^4.2.7",
|
||||
"@0x/json-schemas": "^6.1.3",
|
||||
"@0x/protocol-utils": "^1.8.4",
|
||||
"@0x/quote-server": "^6.0.2",
|
||||
"@0x/types": "^3.3.3",
|
||||
"@0x/typescript-typings": "^5.2.0",
|
||||
"@0x/utils": "^6.4.3",
|
||||
"@0x/web3-wrapper": "^7.5.3",
|
||||
"@balancer-labs/sor": "0.3.2",
|
||||
"@bancor/sdk": "0.2.9",
|
||||
"@ethersproject/abi": "^5.0.1",
|
||||
@@ -83,7 +83,7 @@
|
||||
"axios-mock-adapter": "^1.19.0",
|
||||
"cream-sor": "^0.3.3",
|
||||
"decimal.js": "^10.2.0",
|
||||
"ethereum-types": "^3.6.0",
|
||||
"ethereum-types": "^3.5.0",
|
||||
"ethereumjs-util": "^7.0.10",
|
||||
"fast-abi": "^0.0.2",
|
||||
"graphql": "^15.4.0",
|
||||
@@ -92,20 +92,20 @@
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^5.6.2",
|
||||
"@0x/abi-gen": "^5.6.0",
|
||||
"@0x/contracts-asset-proxy": "^3.7.19",
|
||||
"@0x/contracts-exchange": "^3.2.38",
|
||||
"@0x/contracts-exchange-libs": "^4.3.37",
|
||||
"@0x/contracts-gen": "^2.0.40",
|
||||
"@0x/contracts-test-utils": "^5.4.11",
|
||||
"@0x/contracts-utils": "^4.8.1",
|
||||
"@0x/contracts-gen": "^2.0.38",
|
||||
"@0x/contracts-test-utils": "^5.4.10",
|
||||
"@0x/contracts-utils": "^4.7.18",
|
||||
"@0x/mesh-rpc-client": "^9.4.2",
|
||||
"@0x/migrations": "^8.1.6",
|
||||
"@0x/sol-compiler": "^4.7.5",
|
||||
"@0x/subproviders": "^6.6.0",
|
||||
"@0x/migrations": "^8.1.4",
|
||||
"@0x/sol-compiler": "^4.7.3",
|
||||
"@0x/subproviders": "^6.5.3",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.4",
|
||||
"@0x/types": "^3.3.4",
|
||||
"@0x/types": "^3.3.3",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "12.12.54",
|
||||
|
||||
@@ -50,7 +50,7 @@ const DEFAULT_SWAP_QUOTER_OPTS: SwapQuoterOpts = {
|
||||
samplerGasLimit: 500e6,
|
||||
ethGasStationUrl: ETH_GAS_STATION_API_URL,
|
||||
rfqt: {
|
||||
integratorsWhitelist: [],
|
||||
takerApiKeyWhitelist: [],
|
||||
makerAssetOfferings: {},
|
||||
txOriginBlacklist: new Set(),
|
||||
},
|
||||
|
||||
@@ -88,7 +88,6 @@ export {
|
||||
ExchangeProxyContractOpts,
|
||||
ExchangeProxyRefundReceiver,
|
||||
GetExtensionContractTypeOpts,
|
||||
Integrator,
|
||||
LogFunction,
|
||||
MarketBuySwapQuote,
|
||||
MarketOperation,
|
||||
|
||||
40
packages/asset-swapper/src/rpc_sampler_client.ts
Normal file
40
packages/asset-swapper/src/rpc_sampler_client.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Client as RPCClient, JSONRPCVersionOneResponse } from 'jayson';
|
||||
|
||||
import {
|
||||
LiquidityResponse,
|
||||
RpcLiquidityRequest,
|
||||
RPCSamplerCallback,
|
||||
} from './utils/market_operation_utils/sampler_types';
|
||||
|
||||
const RPC_SAMPLER_SERVICE_URL = '';
|
||||
const RPC_SAMPLER_SERVICE_PORT = 7002;
|
||||
export class RpcSamplerClient {
|
||||
private readonly _rpcUrl: string;
|
||||
private readonly _rpcClient: RPCClient;
|
||||
|
||||
/**
|
||||
* @param rpcUrl URL to the Sampler Service to which JSON RPC requests should be sent
|
||||
*/
|
||||
constructor() {
|
||||
this._rpcUrl = RPC_SAMPLER_SERVICE_URL;
|
||||
this._rpcClient = RPCClient.http({ port: RPC_SAMPLER_SERVICE_PORT });
|
||||
}
|
||||
|
||||
public getSellLiquidity(reqs: RpcLiquidityRequest[], rpcSamplerCallback: RPCSamplerCallback): void {
|
||||
try {
|
||||
this._rpcClient.request(`get_sell_liquidity`, [reqs], (err: any, response: JSONRPCVersionOneResponse) => {
|
||||
return rpcSamplerCallback(err, response.result);
|
||||
});
|
||||
} catch (err) {
|
||||
throw new Error(`error with sampler service: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
public async getSellLiquidityWrapperAsync(reqs: RpcLiquidityRequest[]): Promise<LiquidityResponse[]> {
|
||||
return new Promise(resolve => {
|
||||
this.getSellLiquidity(reqs, (err, liquidityResponses: LiquidityResponse[]) => {
|
||||
return resolve(liquidityResponses);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import * as _ from 'lodash';
|
||||
|
||||
import { artifacts } from './artifacts';
|
||||
import { constants, INVALID_SIGNATURE, KEEP_ALIVE_TTL } from './constants';
|
||||
import { RpcSamplerClient } from './rpc_sampler_client';
|
||||
import {
|
||||
AssetSwapperContractAddresses,
|
||||
MarketBuySwapQuote,
|
||||
@@ -75,7 +76,6 @@ export class SwapQuoter {
|
||||
private readonly _marketOperationUtils: MarketOperationUtils;
|
||||
private readonly _rfqtOptions?: SwapQuoterRfqOpts;
|
||||
private readonly _quoteRequestorHttpClient: AxiosInstance;
|
||||
private readonly _integratorIdsSet: Set<string>;
|
||||
|
||||
/**
|
||||
* Instantiates a new SwapQuoter instance
|
||||
@@ -144,6 +144,7 @@ export class SwapQuoter {
|
||||
this._marketOperationUtils = new MarketOperationUtils(
|
||||
new DexOrderSampler(
|
||||
this.chainId,
|
||||
new RpcSamplerClient(),
|
||||
samplerContract,
|
||||
samplerOverrides,
|
||||
undefined, // pools caches for balancer and cream
|
||||
@@ -165,9 +166,6 @@ export class SwapQuoter {
|
||||
httpsAgent: new HttpsAgent({ keepAlive: true, timeout: KEEP_ALIVE_TTL }),
|
||||
...(rfqt ? rfqt.axiosInstanceOpts : {}),
|
||||
});
|
||||
|
||||
const integratorIds = this._rfqtOptions?.integratorsWhitelist.map(integrator => integrator.integratorId) || [];
|
||||
this._integratorIdsSet = new Set(integratorIds);
|
||||
}
|
||||
|
||||
public async getBatchMarketBuySwapQuoteAsync(
|
||||
@@ -418,11 +416,12 @@ export class SwapQuoter {
|
||||
return isOpenOrder && !willOrderExpire && isFeeTypeAllowed;
|
||||
}; // tslint:disable-line:semicolon
|
||||
|
||||
private _isIntegratorIdWhitelisted(integratorId: string | undefined): boolean {
|
||||
if (!integratorId) {
|
||||
private _isApiKeyWhitelisted(apiKey: string | undefined): boolean {
|
||||
if (!apiKey) {
|
||||
return false;
|
||||
}
|
||||
return this._integratorIdsSet.has(integratorId);
|
||||
const whitelistedApiKeys = this._rfqtOptions ? this._rfqtOptions.takerApiKeyWhitelist : [];
|
||||
return whitelistedApiKeys.includes(apiKey);
|
||||
}
|
||||
|
||||
private _isTxOriginBlacklisted(txOrigin: string | undefined): boolean {
|
||||
@@ -441,19 +440,19 @@ export class SwapQuoter {
|
||||
return rfqt;
|
||||
}
|
||||
// tslint:disable-next-line: boolean-naming
|
||||
const { integrator, nativeExclusivelyRFQ, intentOnFilling, txOrigin } = rfqt;
|
||||
const { apiKey, nativeExclusivelyRFQ, intentOnFilling, txOrigin } = rfqt;
|
||||
// If RFQ-T is enabled and `nativeExclusivelyRFQ` is set, then `ERC20BridgeSource.Native` should
|
||||
// never be excluded.
|
||||
if (nativeExclusivelyRFQ === true && !sourceFilters.isAllowed(ERC20BridgeSource.Native)) {
|
||||
throw new Error('Native liquidity cannot be excluded if "rfqt.nativeExclusivelyRFQ" is set');
|
||||
}
|
||||
|
||||
// If an integrator ID was provided, but the ID is not whitelisted, raise a warning and disable RFQ
|
||||
if (!this._isIntegratorIdWhitelisted(integrator.integratorId)) {
|
||||
// If an API key was provided, but the key is not whitelisted, raise a warning and disable RFQ
|
||||
if (!this._isApiKeyWhitelisted(apiKey)) {
|
||||
if (this._rfqtOptions && this._rfqtOptions.warningLogger) {
|
||||
this._rfqtOptions.warningLogger(
|
||||
{
|
||||
...integrator,
|
||||
apiKey,
|
||||
},
|
||||
'Attempt at using an RFQ API key that is not whitelisted. Disabling RFQ for the request lifetime.',
|
||||
);
|
||||
@@ -477,7 +476,7 @@ export class SwapQuoter {
|
||||
// Otherwise check other RFQ options
|
||||
if (
|
||||
intentOnFilling && // The requestor is asking for a firm quote
|
||||
this._isIntegratorIdWhitelisted(integrator.integratorId) && // A valid API key was provided
|
||||
this._isApiKeyWhitelisted(apiKey) && // A valid API key was provided
|
||||
sourceFilters.isAllowed(ERC20BridgeSource.Native) // Native liquidity is not excluded
|
||||
) {
|
||||
if (!txOrigin || txOrigin === constants.NULL_ADDRESS) {
|
||||
|
||||
@@ -243,7 +243,7 @@ export interface RfqmRequestOptions extends RfqRequestOpts {
|
||||
export interface RfqRequestOpts {
|
||||
takerAddress: string;
|
||||
txOrigin: string;
|
||||
integrator: Integrator;
|
||||
apiKey: string;
|
||||
intentOnFilling: boolean;
|
||||
isIndicative?: boolean;
|
||||
makerEndpointMaxResponseTimeMs?: number;
|
||||
@@ -293,14 +293,8 @@ export interface RfqFirmQuoteValidator {
|
||||
getRfqtTakerFillableAmountsAsync(quotes: RfqOrder[]): Promise<BigNumber[]>;
|
||||
}
|
||||
|
||||
export interface Integrator {
|
||||
integratorId: string;
|
||||
label: string;
|
||||
whitelistIntegratorUrls?: string[];
|
||||
}
|
||||
|
||||
export interface SwapQuoterRfqOpts {
|
||||
integratorsWhitelist: Integrator[];
|
||||
takerApiKeyWhitelist: string[];
|
||||
makerAssetOfferings: RfqMakerAssetOfferings;
|
||||
txOriginBlacklist: Set<string>;
|
||||
altRfqCreds?: {
|
||||
|
||||
@@ -326,7 +326,6 @@ const MIRROR_WRAPPED_TOKENS = {
|
||||
// Mainnet tokens
|
||||
// Not an exhaustive list, just enough so we don't repeat ourselves
|
||||
export const MAINNET_TOKENS = {
|
||||
ETH: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
|
||||
WETH: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
|
||||
// Stable Coins
|
||||
DAI: '0x6b175474e89094c44da98b954eedeac495271d0f',
|
||||
@@ -1206,32 +1205,20 @@ export const KYBER_CONFIG_BY_CHAIN_ID = valueByChainId<KyberSamplerOpts>(
|
||||
export const LIQUIDITY_PROVIDER_REGISTRY_BY_CHAIN_ID = valueByChainId<LiquidityProviderRegistry>(
|
||||
{
|
||||
[ChainId.Mainnet]: {
|
||||
// ['0x1d0d407c5af8c86f0a6494de86e56ae21e46a951']: {
|
||||
// tokens: [
|
||||
// MAINNET_TOKENS.WETH,
|
||||
// MAINNET_TOKENS.USDC,
|
||||
// MAINNET_TOKENS.USDT,
|
||||
// MAINNET_TOKENS.WBTC,
|
||||
// MAINNET_TOKENS.PAX,
|
||||
// MAINNET_TOKENS.LINK,
|
||||
// MAINNET_TOKENS.KNC,
|
||||
// MAINNET_TOKENS.MANA,
|
||||
// MAINNET_TOKENS.DAI,
|
||||
// MAINNET_TOKENS.BUSD,
|
||||
// MAINNET_TOKENS.AAVE,
|
||||
// MAINNET_TOKENS.HT,
|
||||
// ],
|
||||
// gasCost: (takerToken: string, makerToken: string) =>
|
||||
// [takerToken, makerToken].includes(MAINNET_TOKENS.WETH) ? 160e3 : 280e3,
|
||||
// },
|
||||
['0xe82906b6b1b04f631d126c974af57a3a7b6a99d9']: {
|
||||
['0x1d0d407c5af8c86f0a6494de86e56ae21e46a951']: {
|
||||
tokens: [
|
||||
// MAINNET_TOKENS.WETH, // technically ETH but our sampler and mixin handle this
|
||||
MAINNET_TOKENS.ETH,
|
||||
MAINNET_TOKENS.WBTC,
|
||||
MAINNET_TOKENS.WETH,
|
||||
MAINNET_TOKENS.USDC,
|
||||
MAINNET_TOKENS.USDT,
|
||||
MAINNET_TOKENS.WBTC,
|
||||
MAINNET_TOKENS.PAX,
|
||||
MAINNET_TOKENS.LINK,
|
||||
MAINNET_TOKENS.KNC,
|
||||
MAINNET_TOKENS.MANA,
|
||||
MAINNET_TOKENS.DAI,
|
||||
MAINNET_TOKENS.BUSD,
|
||||
MAINNET_TOKENS.AAVE,
|
||||
MAINNET_TOKENS.HT,
|
||||
],
|
||||
gasCost: (takerToken: string, makerToken: string) =>
|
||||
[takerToken, makerToken].includes(MAINNET_TOKENS.WETH) ? 160e3 : 280e3,
|
||||
|
||||
@@ -124,90 +124,90 @@ export class MarketOperationUtils {
|
||||
): Promise<MarketSideLiquidity> {
|
||||
const _opts = { ...DEFAULT_GET_MARKET_ORDERS_OPTS, ...opts };
|
||||
const { makerToken, takerToken } = nativeOrders[0].order;
|
||||
const sampleAmounts = getSampleAmounts(takerAmount, _opts.numSamples, _opts.sampleDistributionBase);
|
||||
// const sampleAmounts = getSampleAmounts(takerAmount, _opts.numSamples, _opts.sampleDistributionBase);
|
||||
|
||||
const requestFilters = new SourceFilters().exclude(_opts.excludedSources).include(_opts.includedSources);
|
||||
const quoteSourceFilters = this._sellSources.merge(requestFilters);
|
||||
const feeSourceFilters = this._feeSources.exclude(_opts.excludedFeeSources);
|
||||
|
||||
// Used to determine whether the tx origin is an EOA or a contract
|
||||
const txOrigin = (_opts.rfqt && _opts.rfqt.txOrigin) || NULL_ADDRESS;
|
||||
// const txOrigin = (_opts.rfqt && _opts.rfqt.txOrigin) || NULL_ADDRESS;
|
||||
|
||||
const sellQuotes = this._sampler.getCachedSellQuotesAsync(quoteSourceFilters.sources, makerToken, takerToken, takerAmount);
|
||||
|
||||
// Call the sampler contract.
|
||||
const samplerPromise = this._sampler.executeAsync(
|
||||
this._sampler.getTokenDecimals([makerToken, takerToken]),
|
||||
// Get native order fillable amounts.
|
||||
this._sampler.getLimitOrderFillableTakerAmounts(nativeOrders, this.contractAddresses.exchangeProxy),
|
||||
// Get ETH -> maker token price.
|
||||
this._sampler.getMedianSellRate(
|
||||
feeSourceFilters.sources,
|
||||
makerToken,
|
||||
this._nativeFeeToken,
|
||||
this._nativeFeeTokenAmount,
|
||||
),
|
||||
// Get ETH -> taker token price.
|
||||
this._sampler.getMedianSellRate(
|
||||
feeSourceFilters.sources,
|
||||
takerToken,
|
||||
this._nativeFeeToken,
|
||||
this._nativeFeeTokenAmount,
|
||||
),
|
||||
// Get sell quotes for taker -> maker.
|
||||
this._sampler.getSellQuotes(quoteSourceFilters.sources, makerToken, takerToken, sampleAmounts),
|
||||
this._sampler.getTwoHopSellQuotes(
|
||||
quoteSourceFilters.isAllowed(ERC20BridgeSource.MultiHop) ? quoteSourceFilters.sources : [],
|
||||
makerToken,
|
||||
takerToken,
|
||||
takerAmount,
|
||||
),
|
||||
this._sampler.isAddressContract(txOrigin),
|
||||
);
|
||||
// const samplerPromise = this._sampler.executeAsync(
|
||||
// // this._sampler.getTokenDecimals([makerToken, takerToken]),
|
||||
// // // Get native order fillable amounts.
|
||||
// // this._sampler.getLimitOrderFillableTakerAmounts(nativeOrders, this.contractAddresses.exchangeProxy),
|
||||
// // // Get ETH -> maker token price.
|
||||
// // this._sampler.getMedianSellRate(
|
||||
// // feeSourceFilters.sources,
|
||||
// // makerToken,
|
||||
// // this._nativeFeeToken,
|
||||
// // this._nativeFeeTokenAmount,
|
||||
// // ),
|
||||
// // // Get ETH -> taker token price.
|
||||
// // this._sampler.getMedianSellRate(
|
||||
// // feeSourceFilters.sources,
|
||||
// // takerToken,
|
||||
// // this._nativeFeeToken,
|
||||
// // this._nativeFeeTokenAmount,
|
||||
// // ),
|
||||
// // Get sell quotes for taker -> maker.
|
||||
// this._sampler.getCachedSellQuotesAsync(quoteSourceFilters.sources, makerToken, takerToken, takerAmount),
|
||||
// // this._sampler.getTwoHopSellQuotes(
|
||||
// // quoteSourceFilters.isAllowed(ERC20BridgeSource.MultiHop) ? quoteSourceFilters.sources : [],
|
||||
// // makerToken,
|
||||
// // takerToken,
|
||||
// // takerAmount,
|
||||
// // ),
|
||||
// // this._sampler.isAddressContract(txOrigin),
|
||||
// );
|
||||
|
||||
// Refresh the cached pools asynchronously if required
|
||||
void this._refreshPoolCacheIfRequiredAsync(takerToken, makerToken);
|
||||
// void this._refreshPoolCacheIfRequiredAsync(takerToken, makerToken);
|
||||
|
||||
const [
|
||||
[
|
||||
tokenDecimals,
|
||||
orderFillableTakerAmounts,
|
||||
outputAmountPerEth,
|
||||
inputAmountPerEth,
|
||||
// tokenDecimals,
|
||||
// orderFillableTakerAmounts,
|
||||
// outputAmountPerEth,
|
||||
// inputAmountPerEth,
|
||||
dexQuotes,
|
||||
rawTwoHopQuotes,
|
||||
isTxOriginContract,
|
||||
],
|
||||
] = await Promise.all([samplerPromise]);
|
||||
// rawTwoHopQuotes,
|
||||
// isTxOriginContract,
|
||||
] = await Promise.all([sellQuotes]);
|
||||
|
||||
// Filter out any invalid two hop quotes where we couldn't find a route
|
||||
const twoHopQuotes = rawTwoHopQuotes.filter(
|
||||
q => q && q.fillData && q.fillData.firstHopSource && q.fillData.secondHopSource,
|
||||
);
|
||||
// const twoHopQuotes = rawTwoHopQuotes.filter(
|
||||
// q => q && q.fillData && q.fillData.firstHopSource && q.fillData.secondHopSource,
|
||||
// );
|
||||
|
||||
const [makerTokenDecimals, takerTokenDecimals] = tokenDecimals;
|
||||
// const [makerTokenDecimals, takerTokenDecimals] = tokenDecimals;
|
||||
|
||||
const isRfqSupported = !!(_opts.rfqt && !isTxOriginContract);
|
||||
const limitOrdersWithFillableAmounts = nativeOrders.map((order, i) => ({
|
||||
...order,
|
||||
...getNativeAdjustedFillableAmountsFromTakerAmount(order, orderFillableTakerAmounts[i]),
|
||||
}));
|
||||
// const isRfqSupported = !!(_opts.rfqt && !isTxOriginContract);
|
||||
// const limitOrdersWithFillableAmounts = nativeOrders.map((order, i) => ({
|
||||
// ...order,
|
||||
// ...getNativeAdjustedFillableAmountsFromTakerAmount(order, orderFillableTakerAmounts[i]),
|
||||
// }));
|
||||
|
||||
return {
|
||||
side: MarketOperation.Sell,
|
||||
inputAmount: takerAmount,
|
||||
inputToken: takerToken,
|
||||
outputToken: makerToken,
|
||||
outputAmountPerEth,
|
||||
inputAmountPerEth,
|
||||
outputAmountPerEth: new BigNumber(1),
|
||||
inputAmountPerEth: new BigNumber(1),
|
||||
quoteSourceFilters,
|
||||
makerTokenDecimals: makerTokenDecimals.toNumber(),
|
||||
takerTokenDecimals: takerTokenDecimals.toNumber(),
|
||||
makerTokenDecimals: 18,
|
||||
takerTokenDecimals: 18,
|
||||
quotes: {
|
||||
nativeOrders: limitOrdersWithFillableAmounts,
|
||||
nativeOrders: [],
|
||||
rfqtIndicativeQuotes: [],
|
||||
twoHopQuotes,
|
||||
twoHopQuotes: [],
|
||||
dexQuotes,
|
||||
},
|
||||
isRfqSupported,
|
||||
isRfqSupported: true,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ChainId } from '@0x/contract-addresses';
|
||||
import { BigNumber, NULL_BYTES } from '@0x/utils';
|
||||
import { RpcSamplerClient } from '../../rpc_sampler_client';
|
||||
|
||||
import { SamplerOverrides } from '../../types';
|
||||
import { ERC20BridgeSamplerContract } from '../../wrappers';
|
||||
@@ -34,6 +35,7 @@ type BatchedOperationResult<T> = T extends BatchedOperation<infer TResult> ? TRe
|
||||
export class DexOrderSampler extends SamplerOperations {
|
||||
constructor(
|
||||
public readonly chainId: ChainId,
|
||||
rpcSamplerClient: RpcSamplerClient,
|
||||
_samplerContract: ERC20BridgeSamplerContract,
|
||||
private readonly _samplerOverrides?: SamplerOverrides,
|
||||
poolsCaches?: { [key in ERC20BridgeSource]: PoolsCache },
|
||||
@@ -41,7 +43,7 @@ export class DexOrderSampler extends SamplerOperations {
|
||||
liquidityProviderRegistry?: LiquidityProviderRegistry,
|
||||
bancorServiceFn: () => Promise<BancorService | undefined> = async () => undefined,
|
||||
) {
|
||||
super(chainId, _samplerContract, poolsCaches, tokenAdjacencyGraph, liquidityProviderRegistry, bancorServiceFn);
|
||||
super(chainId, rpcSamplerClient, _samplerContract, poolsCaches, tokenAdjacencyGraph, liquidityProviderRegistry, bancorServiceFn);
|
||||
}
|
||||
|
||||
/* Type overloads for `executeAsync()`. Could skip this if we would upgrade TS. */
|
||||
|
||||
@@ -3,6 +3,7 @@ import { LimitOrderFields } from '@0x/protocol-utils';
|
||||
import { BigNumber, logUtils } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { RpcSamplerClient } from '../../rpc_sampler_client';
|
||||
import { SamplerCallResult, SignedNativeOrder } from '../../types';
|
||||
import { ERC20BridgeSamplerContract } from '../../wrappers';
|
||||
|
||||
@@ -44,6 +45,7 @@ import { getLiquidityProvidersForPair } from './liquidity_provider_utils';
|
||||
import { getIntermediateTokens } from './multihop_utils';
|
||||
import { BalancerPoolsCache, BalancerV2PoolsCache, CreamPoolsCache, PoolsCache } from './pools_cache';
|
||||
import { SamplerContractOperation } from './sampler_contract_operation';
|
||||
import { Address, LiquidityResponse, RpcLiquidityRequest } from './sampler_types';
|
||||
import { SourceFilters } from './source_filters';
|
||||
import {
|
||||
BalancerFillData,
|
||||
@@ -56,6 +58,7 @@ import {
|
||||
DexSample,
|
||||
DODOFillData,
|
||||
ERC20BridgeSource,
|
||||
FillData,
|
||||
GenericRouterFillData,
|
||||
HopInfo,
|
||||
KyberDmmFillData,
|
||||
@@ -95,6 +98,8 @@ export const BATCH_SOURCE_FILTERS = SourceFilters.all().exclude([ERC20BridgeSour
|
||||
* Composable operations that can be batched in a single transaction,
|
||||
* for use with `DexOrderSampler.executeAsync()`.
|
||||
*/
|
||||
|
||||
export declare type JSONRPCQuoteCallback = (err: Error | null, dexQuotes: Array<Array<DexSample<FillData>>>) => void;
|
||||
export class SamplerOperations {
|
||||
public readonly liquidityProviderRegistry: LiquidityProviderRegistry;
|
||||
public readonly poolsCaches: { [key in SourcesWithPoolsCache]: PoolsCache };
|
||||
@@ -109,6 +114,7 @@ export class SamplerOperations {
|
||||
|
||||
constructor(
|
||||
public readonly chainId: ChainId,
|
||||
protected readonly rpcSamplerClient: RpcSamplerClient,
|
||||
protected readonly _samplerContract: ERC20BridgeSamplerContract,
|
||||
poolsCaches?: { [key in SourcesWithPoolsCache]: PoolsCache },
|
||||
protected readonly tokenAdjacencyGraph: TokenAdjacencyGraph = { default: [] },
|
||||
@@ -130,8 +136,101 @@ export class SamplerOperations {
|
||||
bancorServiceFn()
|
||||
.then(service => (this._bancorService = service))
|
||||
.catch(/* do nothing */);
|
||||
this.rpcSamplerClient = new RpcSamplerClient();
|
||||
}
|
||||
|
||||
public async getTokenDecimalsAsync(tokens: Address[]): Promise<number[]> {
|
||||
return [];
|
||||
// return (await this.rpcSamplerClient.getTokensAsync(tokens)).map(t => t.decimals);
|
||||
}
|
||||
|
||||
public async getCachedSellQuotesAsync(
|
||||
sources: ERC20BridgeSource[],
|
||||
makerToken: string,
|
||||
takerToken: string,
|
||||
takerAmount: BigNumber,
|
||||
// callback: JSONRPCQuoteCallback,
|
||||
): Promise<Array<Array<DexSample<FillData>>>> {
|
||||
// ): Promise<void> {
|
||||
const rpcLiquidityRequests: RpcLiquidityRequest[] = sources.map(source => {
|
||||
return {
|
||||
tokenPath: [makerToken, takerToken],
|
||||
inputAmount: takerAmount.toString(),
|
||||
source,
|
||||
demand: true,
|
||||
};
|
||||
});
|
||||
const liquidityResponses: LiquidityResponse[] = await this.rpcSamplerClient.getSellLiquidityWrapperAsync(rpcLiquidityRequests);
|
||||
const dexQuotes: Array<Array<DexSample<FillData>>> = liquidityResponses.map((liquidityResponse: LiquidityResponse) => {
|
||||
const dexSample: Array<DexSample<FillData>> = liquidityResponse.liquidityCurves.map((point, j) => {
|
||||
const fillData: DexSample = {
|
||||
source: liquidityResponse.source,
|
||||
fillData: point[j].encodedFillData,
|
||||
input: new BigNumber(point[j].sellAmount.toString()), // TODO Romain: prob a better way
|
||||
output: new BigNumber(point[j].buyAmount.toString()),
|
||||
// gasCost: new BigNumber(point[j].gasCost.toString()),
|
||||
};
|
||||
return fillData;
|
||||
});
|
||||
return dexSample;
|
||||
});
|
||||
return dexQuotes;
|
||||
}
|
||||
|
||||
public async getBuyQuotesAsync(
|
||||
sources: ERC20BridgeSource[],
|
||||
makerToken: string,
|
||||
takerToken: string,
|
||||
takerAmount: BigNumber,
|
||||
): Promise<Array<Array<DexSample<FillData>>>> {
|
||||
return [];
|
||||
// const rpcLiquidityRequests: RpcLiquidityRequest[] = sources.map(source => {
|
||||
// return {
|
||||
// tokenPath: [makerToken, takerToken],
|
||||
// inputAmount: takerAmount.toString(),
|
||||
// source,
|
||||
// demand: true,
|
||||
// };
|
||||
// });
|
||||
// const rpcLiquidityResponse = await this.rpcSamplerClient.getBuyLiquidityAsync(rpcLiquidityRequests);
|
||||
// const dexQuotes: Array<Array<DexSample<FillData>>> = rpcLiquidityResponse.map((response, i) => {
|
||||
// const dexSample: Array<DexSample<FillData>> = response.liquidityCurve.map((point, j) => {
|
||||
// const fillData: DexSample = {
|
||||
// source: sources[i],
|
||||
// fillData: point.encodedFillData,
|
||||
// input: point.sellAmount,
|
||||
// output: point.buyAmount,
|
||||
// };
|
||||
// return fillData;
|
||||
// });
|
||||
// return dexSample;
|
||||
// });
|
||||
// return dexQuotes;
|
||||
}
|
||||
|
||||
public async getMedianSellRateAsync(
|
||||
sources: ERC20BridgeSource[],
|
||||
makerToken: string,
|
||||
takerToken: string,
|
||||
takerFillAmount: BigNumber,
|
||||
): Promise<BigNumber> {
|
||||
return new BigNumber(0);
|
||||
// const samples = await this.getSellQuotesAsync(sources, makerToken, takerToken, takerFillAmount);
|
||||
// if (samples.length === 0) {
|
||||
// return ZERO_AMOUNT;
|
||||
// }
|
||||
// const flatSortedSamples = samples
|
||||
// .reduce((acc, v) => acc.concat(...v))
|
||||
// .filter(v => !v.output.isZero())
|
||||
// .sort((a, b) => a.output.comparedTo(b.output));
|
||||
// if (flatSortedSamples.length === 0) {
|
||||
// return ZERO_AMOUNT;
|
||||
// }
|
||||
// const medianSample = flatSortedSamples[Math.floor(flatSortedSamples.length / 2)];
|
||||
// return medianSample.output.div(takerFillAmount);
|
||||
}
|
||||
|
||||
// Legacy
|
||||
public getTokenDecimals(tokens: string[]): BatchedOperation<BigNumber[]> {
|
||||
return new SamplerContractOperation({
|
||||
source: ERC20BridgeSource.Native,
|
||||
@@ -364,7 +463,7 @@ export class SamplerOperations {
|
||||
return new SamplerContractOperation({
|
||||
source,
|
||||
fillData: {
|
||||
poolAddress: '0xe3a207e4225d459095491ea75d30b31968dff887',
|
||||
poolAddress: providerAddress,
|
||||
gasCost,
|
||||
},
|
||||
contract: this._samplerContract,
|
||||
@@ -1258,29 +1357,18 @@ export class SamplerOperations {
|
||||
this.getShellSellQuotes(pool, makerToken, takerToken, takerFillAmounts, source),
|
||||
);
|
||||
case ERC20BridgeSource.LiquidityProvider:
|
||||
const { poolAddress: clipperPoolAddress, tokens: clipperTokens } = CLIPPER_INFO_BY_CHAIN[
|
||||
this.chainId
|
||||
];
|
||||
if (
|
||||
clipperPoolAddress === NULL_ADDRESS ||
|
||||
!clipperTokens.includes(makerToken) ||
|
||||
!clipperTokens.includes(takerToken)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
// Clipper requires WETH to be represented as address(0)
|
||||
const adjustedMakerToken =
|
||||
makerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : makerToken;
|
||||
const adjustedTakerToken =
|
||||
takerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : takerToken;
|
||||
// Supports the PLP interface
|
||||
return this.getLiquidityProviderSellQuotes(
|
||||
clipperPoolAddress,
|
||||
adjustedMakerToken,
|
||||
adjustedTakerToken,
|
||||
return getLiquidityProvidersForPair(
|
||||
this.liquidityProviderRegistry,
|
||||
takerToken,
|
||||
makerToken,
|
||||
).map(({ providerAddress, gasCost }) =>
|
||||
this.getLiquidityProviderSellQuotes(
|
||||
providerAddress,
|
||||
makerToken,
|
||||
takerToken,
|
||||
takerFillAmounts,
|
||||
// tslint:disable-next-line: custom-no-magic-numbers
|
||||
0, // Not used for Clipper
|
||||
gasCost,
|
||||
),
|
||||
);
|
||||
case ERC20BridgeSource.MStable:
|
||||
return getShellLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
|
||||
@@ -1428,7 +1516,31 @@ export class SamplerOperations {
|
||||
return this.getLidoSellQuotes(lidoInfo, makerToken, takerToken, takerFillAmounts);
|
||||
}
|
||||
case ERC20BridgeSource.Clipper:
|
||||
const { poolAddress: clipperPoolAddress, tokens: clipperTokens } = CLIPPER_INFO_BY_CHAIN[
|
||||
this.chainId
|
||||
];
|
||||
if (
|
||||
clipperPoolAddress === NULL_ADDRESS ||
|
||||
!clipperTokens.includes(makerToken) ||
|
||||
!clipperTokens.includes(takerToken)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
// Clipper requires WETH to be represented as address(0)
|
||||
const adjustedMakerToken =
|
||||
makerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : makerToken;
|
||||
const adjustedTakerToken =
|
||||
takerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : takerToken;
|
||||
// Supports the PLP interface
|
||||
return this.getLiquidityProviderSellQuotes(
|
||||
clipperPoolAddress,
|
||||
adjustedMakerToken,
|
||||
adjustedTakerToken,
|
||||
takerFillAmounts,
|
||||
// tslint:disable-next-line: custom-no-magic-numbers
|
||||
0, // Not used for Clipper
|
||||
ERC20BridgeSource.Clipper,
|
||||
);
|
||||
default:
|
||||
throw new Error(`Unsupported sell sample source: ${source}`);
|
||||
}
|
||||
@@ -1540,29 +1652,18 @@ export class SamplerOperations {
|
||||
this.getShellBuyQuotes(pool, makerToken, takerToken, makerFillAmounts, source),
|
||||
);
|
||||
case ERC20BridgeSource.LiquidityProvider:
|
||||
const { poolAddress: clipperPoolAddress, tokens: clipperTokens } = CLIPPER_INFO_BY_CHAIN[
|
||||
this.chainId
|
||||
];
|
||||
if (
|
||||
clipperPoolAddress === NULL_ADDRESS ||
|
||||
!clipperTokens.includes(makerToken) ||
|
||||
!clipperTokens.includes(takerToken)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
// Clipper requires WETH to be represented as address(0)
|
||||
const adjustedMakerToken =
|
||||
makerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : makerToken;
|
||||
const adjustedTakerToken =
|
||||
takerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : takerToken;
|
||||
// Supports the PLP interface
|
||||
return this.getLiquidityProviderBuyQuotes(
|
||||
clipperPoolAddress,
|
||||
adjustedMakerToken,
|
||||
adjustedTakerToken,
|
||||
return getLiquidityProvidersForPair(
|
||||
this.liquidityProviderRegistry,
|
||||
takerToken,
|
||||
makerToken,
|
||||
).map(({ providerAddress, gasCost }) =>
|
||||
this.getLiquidityProviderBuyQuotes(
|
||||
providerAddress,
|
||||
makerToken,
|
||||
takerToken,
|
||||
makerFillAmounts,
|
||||
// tslint:disable-next-line: custom-no-magic-numbers
|
||||
0, // Not used for Clipper
|
||||
gasCost,
|
||||
),
|
||||
);
|
||||
case ERC20BridgeSource.MStable:
|
||||
return getShellLikeInfosForPair(this.chainId, takerToken, makerToken, source).map(pool =>
|
||||
@@ -1705,7 +1806,31 @@ export class SamplerOperations {
|
||||
return this.getLidoBuyQuotes(lidoInfo, makerToken, takerToken, makerFillAmounts);
|
||||
}
|
||||
case ERC20BridgeSource.Clipper:
|
||||
const { poolAddress: clipperPoolAddress, tokens: clipperTokens } = CLIPPER_INFO_BY_CHAIN[
|
||||
this.chainId
|
||||
];
|
||||
if (
|
||||
clipperPoolAddress === NULL_ADDRESS ||
|
||||
!clipperTokens.includes(makerToken) ||
|
||||
!clipperTokens.includes(takerToken)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
// Clipper requires WETH to be represented as address(0)
|
||||
const adjustedMakerToken =
|
||||
makerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : makerToken;
|
||||
const adjustedTakerToken =
|
||||
takerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : takerToken;
|
||||
// Supports the PLP interface
|
||||
return this.getLiquidityProviderBuyQuotes(
|
||||
clipperPoolAddress,
|
||||
adjustedMakerToken,
|
||||
adjustedTakerToken,
|
||||
makerFillAmounts,
|
||||
// tslint:disable-next-line: custom-no-magic-numbers
|
||||
0, // Not used for Clipper
|
||||
ERC20BridgeSource.Clipper,
|
||||
);
|
||||
default:
|
||||
throw new Error(`Unsupported buy sample source: ${source}`);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { ERC20BridgeSource } from './types';
|
||||
|
||||
export type Bytes = string;
|
||||
export type Address = Bytes;
|
||||
|
||||
export type LiquiditySource = ERC20BridgeSource;
|
||||
|
||||
export declare type RPCSamplerCallback = (err: Error | null, liquidityResponses: LiquidityResponse[]) => void;
|
||||
|
||||
export interface RpcLiquidityRequest {
|
||||
tokenPath: Address[];
|
||||
inputAmount: string;
|
||||
source: LiquiditySource;
|
||||
demand: boolean;
|
||||
}
|
||||
|
||||
export interface LiquidityCurvePoint {
|
||||
sellAmount: bigint;
|
||||
buyAmount: bigint;
|
||||
encodedFillData: Bytes;
|
||||
gasCost: number;
|
||||
}
|
||||
|
||||
export interface LiquidityResponse {
|
||||
source: LiquiditySource;
|
||||
liquidityCurves: LiquidityCurvePoint[][];
|
||||
}
|
||||
|
||||
export interface TokenResponse {
|
||||
address: Address;
|
||||
symbol: string;
|
||||
decimals: number;
|
||||
gasCost: number;
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import { QuoteRequestor } from '../../utils/quote_requestor';
|
||||
import { PriceComparisonsReport, QuoteReport } from '../quote_report_generator';
|
||||
|
||||
import { CollapsedPath } from './path';
|
||||
import { LiquiditySource } from './sampler_types';
|
||||
import { SourceFilters } from './source_filters';
|
||||
|
||||
/**
|
||||
@@ -175,6 +176,7 @@ export interface DexSample<TFillData extends FillData = FillData> {
|
||||
fillData: TFillData;
|
||||
input: BigNumber;
|
||||
output: BigNumber;
|
||||
// gasCost: BigNumber;
|
||||
}
|
||||
export interface CurveFillData extends FillData {
|
||||
fromTokenIdx: number;
|
||||
|
||||
@@ -14,7 +14,6 @@ import { constants } from '../constants';
|
||||
import {
|
||||
AltQuoteModel,
|
||||
AltRfqMakerAssetOfferings,
|
||||
Integrator,
|
||||
LogFunction,
|
||||
MarketOperation,
|
||||
RfqMakerAssetOfferings,
|
||||
@@ -62,31 +61,6 @@ export interface MetricsProxy {
|
||||
* @param expirationTimeSeconds the expiration time in seconds
|
||||
*/
|
||||
incrementFillRatioWarningCounter(isLastLook: boolean, maker: string): void;
|
||||
|
||||
/**
|
||||
* Logs the outcome of a network (HTTP) interaction with a market maker.
|
||||
*
|
||||
* @param interaction.isLastLook true if the request is RFQM
|
||||
* @param interaction.integrator the integrator that is requesting the RFQ quote
|
||||
* @param interaction.url the URL of the market maker
|
||||
* @param interaction.quoteType indicative or firm quote
|
||||
* @param interaction.statusCode the statusCode returned by a market maker
|
||||
* @param interaction.latencyMs the latency of the HTTP request (in ms)
|
||||
* @param interaction.included if a firm quote that was returned got included in the next step of processing.
|
||||
* NOTE: this does not mean that the request returned a valid fillable order. It just
|
||||
* means that the network response was successful.
|
||||
*/
|
||||
logRfqMakerNetworkInteraction(interaction: {
|
||||
isLastLook: boolean;
|
||||
integrator: Integrator;
|
||||
url: string;
|
||||
quoteType: 'firm' | 'indicative';
|
||||
statusCode: number | undefined;
|
||||
latencyMs: number;
|
||||
included: boolean;
|
||||
sellTokenAddress: string;
|
||||
buyTokenAddress: string;
|
||||
}): void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,42 +178,6 @@ export class QuoteRequestor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets both standard RFQ makers and "alternative" RFQ makers and combines them together
|
||||
* in a single configuration map. If an integration key whitelist is present, it will be used
|
||||
* to filter a specific makers.
|
||||
*
|
||||
* @param options the RfqmRequestOptions passed in
|
||||
* @param assetOfferings the RFQM or RFQT maker offerings
|
||||
* @returns a list of TypedMakerUrl instances
|
||||
*/
|
||||
public static getTypedMakerUrlsAndWhitelist(
|
||||
options: Pick<RfqmRequestOptions, 'integrator' | 'altRfqAssetOfferings'>,
|
||||
assetOfferings: RfqMakerAssetOfferings,
|
||||
): TypedMakerUrl[] {
|
||||
const standardUrls = Object.keys(assetOfferings).map(
|
||||
(mm: string): TypedMakerUrl => {
|
||||
return { pairType: RfqPairType.Standard, url: mm };
|
||||
},
|
||||
);
|
||||
const altUrls = options.altRfqAssetOfferings
|
||||
? Object.keys(options.altRfqAssetOfferings).map(
|
||||
(mm: string): TypedMakerUrl => {
|
||||
return { pairType: RfqPairType.Alt, url: mm };
|
||||
},
|
||||
)
|
||||
: [];
|
||||
|
||||
let typedMakerUrls = standardUrls.concat(altUrls);
|
||||
|
||||
// If there is a whitelist, only allow approved maker URLs
|
||||
if (options.integrator.whitelistIntegratorUrls !== undefined) {
|
||||
const whitelist = new Set(options.integrator.whitelistIntegratorUrls.map(key => key.toLowerCase()));
|
||||
typedMakerUrls = typedMakerUrls.filter(makerUrl => whitelist.has(makerUrl.url.toLowerCase()));
|
||||
}
|
||||
return typedMakerUrls;
|
||||
}
|
||||
|
||||
public static getDurationUntilExpirationMs(expirationTimeSeconds: BigNumber): BigNumber {
|
||||
const expirationTimeMs = expirationTimeSeconds.times(constants.ONE_SECOND_MS);
|
||||
const currentTimeMs = new BigNumber(Date.now());
|
||||
@@ -463,6 +401,21 @@ export class QuoteRequestor {
|
||||
}
|
||||
})();
|
||||
|
||||
const standardUrls = Object.keys(assetOfferings).map(
|
||||
(mm: string): TypedMakerUrl => {
|
||||
return { pairType: RfqPairType.Standard, url: mm };
|
||||
},
|
||||
);
|
||||
const altUrls = options.altRfqAssetOfferings
|
||||
? Object.keys(options.altRfqAssetOfferings).map(
|
||||
(mm: string): TypedMakerUrl => {
|
||||
return { pairType: RfqPairType.Alt, url: mm };
|
||||
},
|
||||
)
|
||||
: [];
|
||||
|
||||
const typedMakerUrls = standardUrls.concat(altUrls);
|
||||
|
||||
const timeoutMs =
|
||||
options.makerEndpointMaxResponseTimeMs ||
|
||||
constants.DEFAULT_RFQT_REQUEST_OPTS.makerEndpointMaxResponseTimeMs!;
|
||||
@@ -474,25 +427,11 @@ export class QuoteRequestor {
|
||||
cancelTokenSource.cancel('timeout via cancel token');
|
||||
}, timeoutMs + bufferMs);
|
||||
|
||||
const typedMakerUrls = QuoteRequestor.getTypedMakerUrlsAndWhitelist(options, assetOfferings);
|
||||
const quotePromises = typedMakerUrls.map(async typedMakerUrl => {
|
||||
// filter out requests to skip
|
||||
const isBlacklisted = rfqMakerBlacklist.isMakerBlacklisted(typedMakerUrl.url);
|
||||
const partialLogEntry = { url: typedMakerUrl.url, quoteType, requestParams, isBlacklisted };
|
||||
const { isLastLook, integrator } = options;
|
||||
const { sellTokenAddress, buyTokenAddress } = requestParams;
|
||||
if (isBlacklisted) {
|
||||
this._metrics?.logRfqMakerNetworkInteraction({
|
||||
isLastLook: false,
|
||||
url: typedMakerUrl.url,
|
||||
quoteType,
|
||||
statusCode: undefined,
|
||||
sellTokenAddress,
|
||||
buyTokenAddress,
|
||||
latencyMs: 0,
|
||||
included: false,
|
||||
integrator,
|
||||
});
|
||||
this._infoLogger({ rfqtMakerInteraction: { ...partialLogEntry } });
|
||||
return;
|
||||
} else if (
|
||||
@@ -511,32 +450,18 @@ export class QuoteRequestor {
|
||||
try {
|
||||
if (typedMakerUrl.pairType === RfqPairType.Standard) {
|
||||
const response = await this._quoteRequestorHttpClient.get(`${typedMakerUrl.url}/${quotePath}`, {
|
||||
headers: {
|
||||
'0x-api-key': options.integrator.integratorId,
|
||||
'0x-integrator-id': options.integrator.integratorId,
|
||||
},
|
||||
headers: { '0x-api-key': options.apiKey },
|
||||
params: requestParams,
|
||||
timeout: timeoutMs,
|
||||
cancelToken: cancelTokenSource.token,
|
||||
});
|
||||
const latencyMs = Date.now() - timeBeforeAwait;
|
||||
this._metrics?.logRfqMakerNetworkInteraction({
|
||||
isLastLook: isLastLook || false,
|
||||
url: typedMakerUrl.url,
|
||||
quoteType,
|
||||
statusCode: response.status,
|
||||
sellTokenAddress,
|
||||
buyTokenAddress,
|
||||
latencyMs,
|
||||
included: true,
|
||||
integrator,
|
||||
});
|
||||
this._infoLogger({
|
||||
rfqtMakerInteraction: {
|
||||
...partialLogEntry,
|
||||
response: {
|
||||
included: true,
|
||||
apiKey: options.integrator.integratorId,
|
||||
apiKey: options.apiKey,
|
||||
takerAddress: requestParams.takerAddress,
|
||||
txOrigin: requestParams.txOrigin,
|
||||
statusCode: response.status,
|
||||
@@ -554,7 +479,7 @@ export class QuoteRequestor {
|
||||
typedMakerUrl.url,
|
||||
this._altRfqCreds.altRfqApiKey,
|
||||
this._altRfqCreds.altRfqProfile,
|
||||
options.integrator.integratorId,
|
||||
options.apiKey,
|
||||
quoteType === 'firm' ? AltQuoteModel.Firm : AltQuoteModel.Indicative,
|
||||
makerToken,
|
||||
takerToken,
|
||||
@@ -567,23 +492,12 @@ export class QuoteRequestor {
|
||||
);
|
||||
|
||||
const latencyMs = Date.now() - timeBeforeAwait;
|
||||
this._metrics?.logRfqMakerNetworkInteraction({
|
||||
isLastLook: isLastLook || false,
|
||||
url: typedMakerUrl.url,
|
||||
quoteType,
|
||||
statusCode: quote.status,
|
||||
sellTokenAddress,
|
||||
buyTokenAddress,
|
||||
latencyMs,
|
||||
included: true,
|
||||
integrator,
|
||||
});
|
||||
this._infoLogger({
|
||||
rfqtMakerInteraction: {
|
||||
...partialLogEntry,
|
||||
response: {
|
||||
included: true,
|
||||
apiKey: options.integrator.integratorId,
|
||||
apiKey: options.apiKey,
|
||||
takerAddress: requestParams.takerAddress,
|
||||
txOrigin: requestParams.txOrigin,
|
||||
statusCode: quote.status,
|
||||
@@ -597,23 +511,12 @@ export class QuoteRequestor {
|
||||
} catch (err) {
|
||||
// log error if any
|
||||
const latencyMs = Date.now() - timeBeforeAwait;
|
||||
this._metrics?.logRfqMakerNetworkInteraction({
|
||||
isLastLook: isLastLook || false,
|
||||
url: typedMakerUrl.url,
|
||||
quoteType,
|
||||
statusCode: err.response?.status,
|
||||
sellTokenAddress,
|
||||
buyTokenAddress,
|
||||
latencyMs,
|
||||
included: false,
|
||||
integrator,
|
||||
});
|
||||
this._infoLogger({
|
||||
rfqtMakerInteraction: {
|
||||
...partialLogEntry,
|
||||
response: {
|
||||
included: false,
|
||||
apiKey: options.integrator.integratorId,
|
||||
apiKey: options.apiKey,
|
||||
takerAddress: requestParams.takerAddress,
|
||||
txOrigin: requestParams.txOrigin,
|
||||
statusCode: err.response ? err.response.status : undefined,
|
||||
@@ -624,7 +527,7 @@ export class QuoteRequestor {
|
||||
rfqMakerBlacklist.logTimeoutOrLackThereof(typedMakerUrl.url, latencyMs >= timeoutMs);
|
||||
this._warningLogger(
|
||||
convertIfAxiosError(err),
|
||||
`Failed to get RFQ-T ${quoteType} quote from market maker endpoint ${typedMakerUrl.url} for integrator ${options.integrator.integratorId} (${options.integrator.label}) for taker address ${options.takerAddress} and tx origin ${options.txOrigin}`,
|
||||
`Failed to get RFQ-T ${quoteType} quote from market maker endpoint ${typedMakerUrl.url} for API key ${options.apiKey} for taker address ${options.takerAddress} and tx origin ${options.txOrigin}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,11 +28,7 @@ export const rfqtMocker = {
|
||||
// Mock out RFQT responses
|
||||
for (const mockedResponse of mockedResponses) {
|
||||
const { endpoint, requestApiKey, requestParams, responseData, responseCode } = mockedResponse;
|
||||
const requestHeaders = {
|
||||
Accept: 'application/json, text/plain, */*',
|
||||
'0x-api-key': requestApiKey,
|
||||
'0x-integrator-id': requestApiKey,
|
||||
};
|
||||
const requestHeaders = { Accept: 'application/json, text/plain, */*', '0x-api-key': requestApiKey };
|
||||
mockedAxios
|
||||
.onGet(`${endpoint}/${quoteType}`, { params: requestParams }, requestHeaders)
|
||||
.replyOnce(responseCode, responseData);
|
||||
|
||||
@@ -1,567 +0,0 @@
|
||||
import { ChainId, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
|
||||
import {
|
||||
constants,
|
||||
expect,
|
||||
getRandomFloat,
|
||||
getRandomInteger,
|
||||
randomAddress,
|
||||
toBaseUnitAmount,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { FillQuoteTransformerOrderType, LimitOrderFields, SignatureType } from '@0x/protocol-utils';
|
||||
import { BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { SignedOrder } from '../src/types';
|
||||
import { DexOrderSampler, getSampleAmounts } from '../src/utils/market_operation_utils/sampler';
|
||||
import { ERC20BridgeSource, TokenAdjacencyGraph } from '../src/utils/market_operation_utils/types';
|
||||
|
||||
import { MockSamplerContract } from './utils/mock_sampler_contract';
|
||||
import { generatePseudoRandomSalt } from './utils/utils';
|
||||
|
||||
const CHAIN_ID = 1;
|
||||
const EMPTY_BYTES32 = '0x0000000000000000000000000000000000000000000000000000000000000000';
|
||||
// tslint:disable: custom-no-magic-numbers
|
||||
describe('DexSampler tests', () => {
|
||||
const MAKER_TOKEN = randomAddress();
|
||||
const TAKER_TOKEN = randomAddress();
|
||||
const chainId = ChainId.Mainnet;
|
||||
|
||||
const wethAddress = getContractAddressesForChainOrThrow(CHAIN_ID).etherToken;
|
||||
const exchangeProxyAddress = getContractAddressesForChainOrThrow(CHAIN_ID).exchangeProxy;
|
||||
|
||||
const tokenAdjacencyGraph: TokenAdjacencyGraph = { default: [wethAddress] };
|
||||
|
||||
describe('getSampleAmounts()', () => {
|
||||
const FILL_AMOUNT = getRandomInteger(1, 1e18);
|
||||
const NUM_SAMPLES = 16;
|
||||
|
||||
it('generates the correct number of amounts', () => {
|
||||
const amounts = getSampleAmounts(FILL_AMOUNT, NUM_SAMPLES);
|
||||
expect(amounts).to.be.length(NUM_SAMPLES);
|
||||
});
|
||||
|
||||
it('first amount is nonzero', () => {
|
||||
const amounts = getSampleAmounts(FILL_AMOUNT, NUM_SAMPLES);
|
||||
expect(amounts[0]).to.not.bignumber.eq(0);
|
||||
});
|
||||
|
||||
it('last amount is the fill amount', () => {
|
||||
const amounts = getSampleAmounts(FILL_AMOUNT, NUM_SAMPLES);
|
||||
expect(amounts[NUM_SAMPLES - 1]).to.bignumber.eq(FILL_AMOUNT);
|
||||
});
|
||||
|
||||
it('can generate a single amount', () => {
|
||||
const amounts = getSampleAmounts(FILL_AMOUNT, 1);
|
||||
expect(amounts).to.be.length(1);
|
||||
expect(amounts[0]).to.bignumber.eq(FILL_AMOUNT);
|
||||
});
|
||||
|
||||
it('generates ascending amounts', () => {
|
||||
const amounts = getSampleAmounts(FILL_AMOUNT, NUM_SAMPLES);
|
||||
for (const i of _.times(NUM_SAMPLES).slice(1)) {
|
||||
const prev = amounts[i - 1];
|
||||
const amount = amounts[i];
|
||||
expect(prev).to.bignumber.lt(amount);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function createOrder(overrides?: Partial<LimitOrderFields>): SignedOrder<LimitOrderFields> {
|
||||
const o: SignedOrder<LimitOrderFields> = {
|
||||
order: {
|
||||
salt: generatePseudoRandomSalt(),
|
||||
expiry: getRandomInteger(0, 2 ** 64),
|
||||
makerToken: MAKER_TOKEN,
|
||||
takerToken: TAKER_TOKEN,
|
||||
makerAmount: getRandomInteger(1, 1e18),
|
||||
takerAmount: getRandomInteger(1, 1e18),
|
||||
takerTokenFeeAmount: constants.ZERO_AMOUNT,
|
||||
chainId: CHAIN_ID,
|
||||
pool: EMPTY_BYTES32,
|
||||
feeRecipient: NULL_ADDRESS,
|
||||
sender: NULL_ADDRESS,
|
||||
maker: NULL_ADDRESS,
|
||||
taker: NULL_ADDRESS,
|
||||
verifyingContract: exchangeProxyAddress,
|
||||
...overrides,
|
||||
},
|
||||
signature: { v: 1, r: hexUtils.random(), s: hexUtils.random(), signatureType: SignatureType.EthSign },
|
||||
type: FillQuoteTransformerOrderType.Limit,
|
||||
};
|
||||
return o;
|
||||
}
|
||||
const ORDERS = _.times(4, () => createOrder());
|
||||
const SIMPLE_ORDERS = ORDERS.map(o => _.omit(o.order, ['chainId', 'verifyingContract']));
|
||||
|
||||
describe('operations', () => {
|
||||
it('getLimitOrderFillableMakerAssetAmounts()', async () => {
|
||||
const expectedFillableAmounts = ORDERS.map(() => getRandomInteger(0, 100e18));
|
||||
const sampler = new MockSamplerContract({
|
||||
getLimitOrderFillableMakerAssetAmounts: (orders, signatures) => {
|
||||
expect(orders).to.deep.eq(SIMPLE_ORDERS);
|
||||
expect(signatures).to.deep.eq(ORDERS.map(o => o.signature));
|
||||
return expectedFillableAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
chainId,
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getLimitOrderFillableMakerAmounts(ORDERS, exchangeProxyAddress),
|
||||
);
|
||||
expect(fillableAmounts).to.deep.eq(expectedFillableAmounts);
|
||||
});
|
||||
|
||||
it('getLimitOrderFillableTakerAssetAmounts()', async () => {
|
||||
const expectedFillableAmounts = ORDERS.map(() => getRandomInteger(0, 100e18));
|
||||
const sampler = new MockSamplerContract({
|
||||
getLimitOrderFillableTakerAssetAmounts: (orders, signatures) => {
|
||||
expect(orders).to.deep.eq(SIMPLE_ORDERS);
|
||||
expect(signatures).to.deep.eq(ORDERS.map(o => o.signature));
|
||||
return expectedFillableAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
chainId,
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getLimitOrderFillableTakerAmounts(ORDERS, exchangeProxyAddress),
|
||||
);
|
||||
expect(fillableAmounts).to.deep.eq(expectedFillableAmounts);
|
||||
});
|
||||
|
||||
it('getKyberSellQuotes()', async () => {
|
||||
const expectedTakerToken = randomAddress();
|
||||
const expectedMakerToken = randomAddress();
|
||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||
const sampler = new MockSamplerContract({
|
||||
sampleSellsFromKyberNetwork: (_reserveOffset, takerToken, makerToken, fillAmounts) => {
|
||||
expect(takerToken).to.eq(expectedTakerToken);
|
||||
expect(makerToken).to.eq(expectedMakerToken);
|
||||
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||
return ['0x', '0x', expectedMakerFillAmounts];
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
chainId,
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getKyberSellQuotes(
|
||||
{ hintHandler: randomAddress(), networkProxy: randomAddress(), weth: randomAddress() },
|
||||
new BigNumber(0),
|
||||
expectedMakerToken,
|
||||
expectedTakerToken,
|
||||
expectedTakerFillAmounts,
|
||||
),
|
||||
);
|
||||
expect(fillableAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||
});
|
||||
|
||||
it('getLiquidityProviderSellQuotes()', async () => {
|
||||
const expectedMakerToken = randomAddress();
|
||||
const expectedTakerToken = randomAddress();
|
||||
const poolAddress = randomAddress();
|
||||
const gasCost = 123;
|
||||
const sampler = new MockSamplerContract({
|
||||
sampleSellsFromLiquidityProvider: (providerAddress, takerToken, makerToken, _fillAmounts) => {
|
||||
expect(providerAddress).to.eq(poolAddress);
|
||||
expect(takerToken).to.eq(expectedTakerToken);
|
||||
expect(makerToken).to.eq(expectedMakerToken);
|
||||
return [toBaseUnitAmount(1001)];
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
chainId,
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
{
|
||||
[poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost },
|
||||
},
|
||||
async () => undefined,
|
||||
);
|
||||
const [result] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getSellQuotes(
|
||||
[ERC20BridgeSource.LiquidityProvider],
|
||||
expectedMakerToken,
|
||||
expectedTakerToken,
|
||||
[toBaseUnitAmount(1000)],
|
||||
),
|
||||
);
|
||||
expect(result).to.deep.equal([
|
||||
[
|
||||
{
|
||||
source: 'LiquidityProvider',
|
||||
output: toBaseUnitAmount(1001),
|
||||
input: toBaseUnitAmount(1000),
|
||||
fillData: { poolAddress, gasCost },
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('getLiquidityProviderBuyQuotes()', async () => {
|
||||
const expectedMakerToken = randomAddress();
|
||||
const expectedTakerToken = randomAddress();
|
||||
const poolAddress = randomAddress();
|
||||
const gasCost = 321;
|
||||
const sampler = new MockSamplerContract({
|
||||
sampleBuysFromLiquidityProvider: (providerAddress, takerToken, makerToken, _fillAmounts) => {
|
||||
expect(providerAddress).to.eq(poolAddress);
|
||||
expect(takerToken).to.eq(expectedTakerToken);
|
||||
expect(makerToken).to.eq(expectedMakerToken);
|
||||
return [toBaseUnitAmount(999)];
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
chainId,
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
{
|
||||
[poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost },
|
||||
},
|
||||
async () => undefined,
|
||||
);
|
||||
const [result] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getBuyQuotes(
|
||||
[ERC20BridgeSource.LiquidityProvider],
|
||||
expectedMakerToken,
|
||||
expectedTakerToken,
|
||||
[toBaseUnitAmount(1000)],
|
||||
),
|
||||
);
|
||||
expect(result).to.deep.equal([
|
||||
[
|
||||
{
|
||||
source: 'LiquidityProvider',
|
||||
output: toBaseUnitAmount(999),
|
||||
input: toBaseUnitAmount(1000),
|
||||
fillData: { poolAddress, gasCost },
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('getUniswapSellQuotes()', async () => {
|
||||
const expectedTakerToken = randomAddress();
|
||||
const expectedMakerToken = randomAddress();
|
||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||
const sampler = new MockSamplerContract({
|
||||
sampleSellsFromUniswap: (_router, takerToken, makerToken, fillAmounts) => {
|
||||
expect(takerToken).to.eq(expectedTakerToken);
|
||||
expect(makerToken).to.eq(expectedMakerToken);
|
||||
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||
return expectedMakerFillAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
chainId,
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getUniswapSellQuotes(
|
||||
randomAddress(),
|
||||
expectedMakerToken,
|
||||
expectedTakerToken,
|
||||
expectedTakerFillAmounts,
|
||||
),
|
||||
);
|
||||
expect(fillableAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||
});
|
||||
|
||||
it('getUniswapV2SellQuotes()', async () => {
|
||||
const expectedTakerToken = randomAddress();
|
||||
const expectedMakerToken = randomAddress();
|
||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||
const sampler = new MockSamplerContract({
|
||||
sampleSellsFromUniswapV2: (_router, path, fillAmounts) => {
|
||||
expect(path).to.deep.eq([expectedMakerToken, expectedTakerToken]);
|
||||
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||
return expectedMakerFillAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
chainId,
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getUniswapV2SellQuotes(
|
||||
NULL_ADDRESS,
|
||||
[expectedMakerToken, expectedTakerToken],
|
||||
expectedTakerFillAmounts,
|
||||
),
|
||||
);
|
||||
expect(fillableAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||
});
|
||||
|
||||
it('getUniswapBuyQuotes()', async () => {
|
||||
const expectedTakerToken = randomAddress();
|
||||
const expectedMakerToken = randomAddress();
|
||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||
const sampler = new MockSamplerContract({
|
||||
sampleBuysFromUniswap: (_router, takerToken, makerToken, fillAmounts) => {
|
||||
expect(takerToken).to.eq(expectedTakerToken);
|
||||
expect(makerToken).to.eq(expectedMakerToken);
|
||||
expect(fillAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||
return expectedTakerFillAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
chainId,
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getUniswapBuyQuotes(
|
||||
randomAddress(),
|
||||
expectedMakerToken,
|
||||
expectedTakerToken,
|
||||
expectedMakerFillAmounts,
|
||||
),
|
||||
);
|
||||
expect(fillableAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||
});
|
||||
|
||||
interface RatesBySource {
|
||||
[src: string]: BigNumber;
|
||||
}
|
||||
|
||||
it('getSellQuotes()', async () => {
|
||||
const expectedTakerToken = randomAddress();
|
||||
const expectedMakerToken = randomAddress();
|
||||
const sources = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.UniswapV2];
|
||||
const ratesBySource: RatesBySource = {
|
||||
[ERC20BridgeSource.Kyber]: getRandomFloat(0, 100),
|
||||
[ERC20BridgeSource.Uniswap]: getRandomFloat(0, 100),
|
||||
[ERC20BridgeSource.UniswapV2]: getRandomFloat(0, 100),
|
||||
};
|
||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 3);
|
||||
let uniswapRouter: string;
|
||||
let uniswapV2Router: string;
|
||||
const sampler = new MockSamplerContract({
|
||||
sampleSellsFromUniswap: (router, takerToken, makerToken, fillAmounts) => {
|
||||
uniswapRouter = router;
|
||||
expect(takerToken).to.eq(expectedTakerToken);
|
||||
expect(makerToken).to.eq(expectedMakerToken);
|
||||
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.Uniswap]).integerValue());
|
||||
},
|
||||
sampleSellsFromUniswapV2: (router, path, fillAmounts) => {
|
||||
uniswapV2Router = router;
|
||||
if (path.length === 2) {
|
||||
expect(path).to.deep.eq([expectedTakerToken, expectedMakerToken]);
|
||||
} else if (path.length === 3) {
|
||||
expect(path).to.deep.eq([expectedTakerToken, wethAddress, expectedMakerToken]);
|
||||
} else {
|
||||
expect(path).to.have.lengthOf.within(2, 3);
|
||||
}
|
||||
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.UniswapV2]).integerValue());
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
chainId,
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
tokenAdjacencyGraph,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [quotes] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getSellQuotes(
|
||||
sources,
|
||||
expectedMakerToken,
|
||||
expectedTakerToken,
|
||||
expectedTakerFillAmounts,
|
||||
),
|
||||
);
|
||||
const expectedQuotes = sources.map(s =>
|
||||
expectedTakerFillAmounts.map(a => ({
|
||||
source: s,
|
||||
input: a,
|
||||
output: a.times(ratesBySource[s]).integerValue(),
|
||||
fillData: (() => {
|
||||
if (s === ERC20BridgeSource.UniswapV2) {
|
||||
return {
|
||||
router: uniswapV2Router,
|
||||
tokenAddressPath: [expectedTakerToken, expectedMakerToken],
|
||||
};
|
||||
}
|
||||
// TODO jacob pass through
|
||||
if (s === ERC20BridgeSource.Uniswap) {
|
||||
return { router: uniswapRouter };
|
||||
}
|
||||
return {};
|
||||
})(),
|
||||
})),
|
||||
);
|
||||
const uniswapV2ETHQuotes = [
|
||||
expectedTakerFillAmounts.map(a => ({
|
||||
source: ERC20BridgeSource.UniswapV2,
|
||||
input: a,
|
||||
output: a.times(ratesBySource[ERC20BridgeSource.UniswapV2]).integerValue(),
|
||||
fillData: {
|
||||
router: uniswapV2Router,
|
||||
tokenAddressPath: [expectedTakerToken, wethAddress, expectedMakerToken],
|
||||
},
|
||||
})),
|
||||
];
|
||||
// extra quote for Uniswap V2, which provides a direct quote (tokenA -> tokenB) AND an ETH quote (tokenA -> ETH -> tokenB)
|
||||
const additionalSourceCount = 1;
|
||||
expect(quotes).to.have.lengthOf(sources.length + additionalSourceCount);
|
||||
expect(quotes).to.deep.eq(expectedQuotes.concat(uniswapV2ETHQuotes));
|
||||
});
|
||||
it('getBuyQuotes()', async () => {
|
||||
const expectedTakerToken = randomAddress();
|
||||
const expectedMakerToken = randomAddress();
|
||||
const sources = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.UniswapV2];
|
||||
const ratesBySource: RatesBySource = {
|
||||
[ERC20BridgeSource.Uniswap]: getRandomFloat(0, 100),
|
||||
[ERC20BridgeSource.UniswapV2]: getRandomFloat(0, 100),
|
||||
};
|
||||
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 3);
|
||||
let uniswapRouter: string;
|
||||
let uniswapV2Router: string;
|
||||
const sampler = new MockSamplerContract({
|
||||
sampleBuysFromUniswap: (router, takerToken, makerToken, fillAmounts) => {
|
||||
uniswapRouter = router;
|
||||
expect(takerToken).to.eq(expectedTakerToken);
|
||||
expect(makerToken).to.eq(expectedMakerToken);
|
||||
expect(fillAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.Uniswap]).integerValue());
|
||||
},
|
||||
sampleBuysFromUniswapV2: (router, path, fillAmounts) => {
|
||||
uniswapV2Router = router;
|
||||
if (path.length === 2) {
|
||||
expect(path).to.deep.eq([expectedTakerToken, expectedMakerToken]);
|
||||
} else if (path.length === 3) {
|
||||
expect(path).to.deep.eq([expectedTakerToken, wethAddress, expectedMakerToken]);
|
||||
} else {
|
||||
expect(path).to.have.lengthOf.within(2, 3);
|
||||
}
|
||||
expect(fillAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.UniswapV2]).integerValue());
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
chainId,
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
tokenAdjacencyGraph,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [quotes] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getBuyQuotes(sources, expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts),
|
||||
);
|
||||
const expectedQuotes = sources.map(s =>
|
||||
expectedMakerFillAmounts.map(a => ({
|
||||
source: s,
|
||||
input: a,
|
||||
output: a.times(ratesBySource[s]).integerValue(),
|
||||
fillData: (() => {
|
||||
if (s === ERC20BridgeSource.UniswapV2) {
|
||||
return {
|
||||
router: uniswapV2Router,
|
||||
tokenAddressPath: [expectedTakerToken, expectedMakerToken],
|
||||
};
|
||||
}
|
||||
if (s === ERC20BridgeSource.Uniswap) {
|
||||
return { router: uniswapRouter };
|
||||
}
|
||||
return {};
|
||||
})(),
|
||||
})),
|
||||
);
|
||||
const uniswapV2ETHQuotes = [
|
||||
expectedMakerFillAmounts.map(a => ({
|
||||
source: ERC20BridgeSource.UniswapV2,
|
||||
input: a,
|
||||
output: a.times(ratesBySource[ERC20BridgeSource.UniswapV2]).integerValue(),
|
||||
fillData: {
|
||||
router: uniswapV2Router,
|
||||
tokenAddressPath: [expectedTakerToken, wethAddress, expectedMakerToken],
|
||||
},
|
||||
})),
|
||||
];
|
||||
// extra quote for Uniswap V2, which provides a direct quote (tokenA -> tokenB) AND an ETH quote (tokenA -> ETH -> tokenB)
|
||||
expect(quotes).to.have.lengthOf(sources.length + 1);
|
||||
expect(quotes).to.deep.eq(expectedQuotes.concat(uniswapV2ETHQuotes));
|
||||
});
|
||||
describe('batched operations', () => {
|
||||
it('getLimitOrderFillableMakerAssetAmounts(), getLimitOrderFillableTakerAssetAmounts()', async () => {
|
||||
const expectedFillableTakerAmounts = ORDERS.map(() => getRandomInteger(0, 100e18));
|
||||
const expectedFillableMakerAmounts = ORDERS.map(() => getRandomInteger(0, 100e18));
|
||||
const sampler = new MockSamplerContract({
|
||||
getLimitOrderFillableMakerAssetAmounts: (orders, signatures) => {
|
||||
expect(orders).to.deep.eq(SIMPLE_ORDERS);
|
||||
expect(signatures).to.deep.eq(ORDERS.map(o => o.signature));
|
||||
return expectedFillableMakerAmounts;
|
||||
},
|
||||
getLimitOrderFillableTakerAssetAmounts: (orders, signatures) => {
|
||||
expect(orders).to.deep.eq(SIMPLE_ORDERS);
|
||||
expect(signatures).to.deep.eq(ORDERS.map(o => o.signature));
|
||||
return expectedFillableTakerAmounts;
|
||||
},
|
||||
});
|
||||
const dexOrderSampler = new DexOrderSampler(
|
||||
chainId,
|
||||
sampler,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
async () => undefined,
|
||||
);
|
||||
const [fillableMakerAmounts, fillableTakerAmounts] = await dexOrderSampler.executeAsync(
|
||||
dexOrderSampler.getLimitOrderFillableMakerAmounts(ORDERS, exchangeProxyAddress),
|
||||
dexOrderSampler.getLimitOrderFillableTakerAmounts(ORDERS, exchangeProxyAddress),
|
||||
);
|
||||
expect(fillableMakerAmounts).to.deep.eq(expectedFillableMakerAmounts);
|
||||
expect(fillableTakerAmounts).to.deep.eq(expectedFillableTakerAmounts);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:disable-next-line: max-file-line-count
|
||||
@@ -16,7 +16,7 @@ import * as _ from 'lodash';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
|
||||
import { MarketOperation, QuoteRequestor, RfqRequestOpts, SignedNativeOrder } from '../src';
|
||||
import { Integrator, NativeOrderWithFillableAmounts } from '../src/types';
|
||||
import { NativeOrderWithFillableAmounts } from '../src/types';
|
||||
import { MarketOperationUtils } from '../src/utils/market_operation_utils/';
|
||||
import {
|
||||
BUY_SOURCE_FILTER_BY_CHAIN_ID,
|
||||
@@ -62,10 +62,6 @@ const SELL_SOURCES = SELL_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources;
|
||||
const TOKEN_ADJACENCY_GRAPH: TokenAdjacencyGraph = { default: [] };
|
||||
|
||||
const SIGNATURE = { v: 1, r: NULL_BYTES, s: NULL_BYTES, signatureType: SignatureType.EthSign };
|
||||
const FOO_INTEGRATOR: Integrator = {
|
||||
integratorId: 'foo',
|
||||
label: 'foo',
|
||||
};
|
||||
|
||||
/**
|
||||
* gets the orders required for a market sell operation by (potentially) merging native orders with
|
||||
@@ -749,7 +745,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
feeSchedule,
|
||||
rfqt: {
|
||||
isIndicative: false,
|
||||
integrator: FOO_INTEGRATOR,
|
||||
apiKey: 'foo',
|
||||
takerAddress: randomAddress(),
|
||||
txOrigin: randomAddress(),
|
||||
intentOnFilling: true,
|
||||
@@ -794,7 +790,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
...DEFAULT_OPTS,
|
||||
rfqt: {
|
||||
isIndicative: false,
|
||||
integrator: FOO_INTEGRATOR,
|
||||
apiKey: 'foo',
|
||||
takerAddress: randomAddress(),
|
||||
intentOnFilling: true,
|
||||
txOrigin: randomAddress(),
|
||||
@@ -841,7 +837,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
...DEFAULT_OPTS,
|
||||
rfqt: {
|
||||
isIndicative: true,
|
||||
integrator: FOO_INTEGRATOR,
|
||||
apiKey: 'foo',
|
||||
takerAddress: randomAddress(),
|
||||
txOrigin: randomAddress(),
|
||||
intentOnFilling: true,
|
||||
@@ -900,10 +896,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
...DEFAULT_OPTS,
|
||||
rfqt: {
|
||||
isIndicative: false,
|
||||
integrator: {
|
||||
integratorId: 'foo',
|
||||
label: 'foo',
|
||||
},
|
||||
apiKey: 'foo',
|
||||
takerAddress: randomAddress(),
|
||||
intentOnFilling: true,
|
||||
txOrigin: randomAddress(),
|
||||
@@ -961,7 +954,7 @@ describe('MarketOperationUtils tests', () => {
|
||||
...DEFAULT_OPTS,
|
||||
rfqt: {
|
||||
isIndicative: false,
|
||||
integrator: FOO_INTEGRATOR,
|
||||
apiKey: 'foo',
|
||||
takerAddress: randomAddress(),
|
||||
txOrigin: randomAddress(),
|
||||
intentOnFilling: true,
|
||||
|
||||
@@ -240,10 +240,7 @@ describe('QuoteRequestor', async () => {
|
||||
MarketOperation.Sell,
|
||||
undefined,
|
||||
{
|
||||
integrator: {
|
||||
integratorId: apiKey,
|
||||
label: 'foo',
|
||||
},
|
||||
apiKey,
|
||||
takerAddress,
|
||||
txOrigin: takerAddress,
|
||||
intentOnFilling: true,
|
||||
@@ -438,10 +435,7 @@ describe('QuoteRequestor', async () => {
|
||||
MarketOperation.Sell,
|
||||
undefined,
|
||||
{
|
||||
integrator: {
|
||||
integratorId: apiKey,
|
||||
label: 'foo',
|
||||
},
|
||||
apiKey,
|
||||
takerAddress,
|
||||
txOrigin: takerAddress,
|
||||
intentOnFilling: true,
|
||||
@@ -557,10 +551,7 @@ describe('QuoteRequestor', async () => {
|
||||
MarketOperation.Sell,
|
||||
undefined,
|
||||
{
|
||||
integrator: {
|
||||
integratorId: apiKey,
|
||||
label: 'foo',
|
||||
},
|
||||
apiKey,
|
||||
takerAddress,
|
||||
txOrigin: takerAddress,
|
||||
intentOnFilling: true,
|
||||
@@ -684,10 +675,7 @@ describe('QuoteRequestor', async () => {
|
||||
MarketOperation.Sell,
|
||||
undefined,
|
||||
{
|
||||
integrator: {
|
||||
integratorId: apiKey,
|
||||
label: 'foo',
|
||||
},
|
||||
apiKey,
|
||||
takerAddress,
|
||||
txOrigin: takerAddress,
|
||||
intentOnFilling: true,
|
||||
@@ -774,10 +762,7 @@ describe('QuoteRequestor', async () => {
|
||||
MarketOperation.Sell,
|
||||
undefined,
|
||||
{
|
||||
integrator: {
|
||||
integratorId: apiKey,
|
||||
label: 'foo',
|
||||
},
|
||||
apiKey,
|
||||
takerAddress,
|
||||
txOrigin: takerAddress,
|
||||
intentOnFilling: true,
|
||||
@@ -838,10 +823,7 @@ describe('QuoteRequestor', async () => {
|
||||
MarketOperation.Buy,
|
||||
undefined,
|
||||
{
|
||||
integrator: {
|
||||
integratorId: apiKey,
|
||||
label: 'foo',
|
||||
},
|
||||
apiKey,
|
||||
takerAddress,
|
||||
txOrigin: takerAddress,
|
||||
intentOnFilling: true,
|
||||
@@ -852,43 +834,6 @@ describe('QuoteRequestor', async () => {
|
||||
quoteRequestorHttpClient,
|
||||
);
|
||||
});
|
||||
it('should be able to handle and filter RFQ offerings', () => {
|
||||
const tests: Array<[string[] | undefined, string[]]> = [
|
||||
[['https://top.maker'], []],
|
||||
[undefined, ['https://foo.bar/', 'https://lorem.ipsum/']],
|
||||
[['https://lorem.ipsum/'], ['https://lorem.ipsum/']],
|
||||
];
|
||||
for (const test of tests) {
|
||||
const [apiKeyWhitelist, results] = test;
|
||||
const response = QuoteRequestor.getTypedMakerUrlsAndWhitelist(
|
||||
{
|
||||
integrator: {
|
||||
integratorId: 'foo',
|
||||
label: 'bar',
|
||||
whitelistIntegratorUrls: apiKeyWhitelist,
|
||||
},
|
||||
altRfqAssetOfferings: {},
|
||||
},
|
||||
{
|
||||
'https://foo.bar/': [
|
||||
[
|
||||
'0xA6cD4cb8c62aCDe44739E3Ed0F1d13E0e31f2d94',
|
||||
'0xF45107c0200a04A8aB9C600cc52A3C89AE5D0489',
|
||||
],
|
||||
],
|
||||
'https://lorem.ipsum/': [
|
||||
[
|
||||
'0xA6cD4cb8c62aCDe44739E3Ed0F1d13E0e31f2d94',
|
||||
'0xF45107c0200a04A8aB9C600cc52A3C89AE5D0489',
|
||||
],
|
||||
],
|
||||
},
|
||||
);
|
||||
const typedUrls = response.map(typed => typed.url);
|
||||
expect(typedUrls).to.eql(results);
|
||||
}
|
||||
});
|
||||
|
||||
it('should return successful alt indicative quotes', async () => {
|
||||
const takerAddress = '0xd209925defc99488e3afff1174e48b4fa628302a';
|
||||
const txOrigin = '0xf209925defc99488e3afff1174e48b4fa628302a';
|
||||
@@ -1110,10 +1055,7 @@ describe('QuoteRequestor', async () => {
|
||||
altScenario.requestedOperation,
|
||||
undefined,
|
||||
{
|
||||
integrator: {
|
||||
integratorId: apiKey,
|
||||
label: 'foo',
|
||||
},
|
||||
apiKey,
|
||||
takerAddress,
|
||||
txOrigin,
|
||||
intentOnFilling: true,
|
||||
|
||||
@@ -48,11 +48,7 @@ export const testHelpers = {
|
||||
// Mock out Standard RFQ-T/M responses
|
||||
for (const mockedResponse of standardMockedResponses) {
|
||||
const { endpoint, requestApiKey, requestParams, responseData, responseCode } = mockedResponse;
|
||||
const requestHeaders = {
|
||||
Accept: 'application/json, text/plain, */*',
|
||||
'0x-api-key': requestApiKey,
|
||||
'0x-integrator-id': requestApiKey,
|
||||
};
|
||||
const requestHeaders = { Accept: 'application/json, text/plain, */*', '0x-api-key': requestApiKey };
|
||||
if (mockedResponse.callback !== undefined) {
|
||||
mockedAxios
|
||||
.onGet(`${endpoint}/${quoteType}`, { params: requestParams }, requestHeaders)
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1631710679,
|
||||
"version": "3.15.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "3.15.0",
|
||||
"changes": [
|
||||
|
||||
@@ -5,10 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v3.15.1 - _September 15, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v3.15.0 - _June 2, 2021_
|
||||
|
||||
* Update artifacts (#237)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contract-artifacts",
|
||||
"version": "3.15.1",
|
||||
"version": "3.15.0",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/packages/contract-artifacts",
|
||||
"devDependencies": {
|
||||
"@0x/utils": "^6.4.4",
|
||||
"@0x/utils": "^6.4.3",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"chai": "^4.0.1",
|
||||
"lodash": "^4.17.11",
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1631710679,
|
||||
"version": "13.17.7",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1630459879,
|
||||
"version": "13.17.6",
|
||||
|
||||
@@ -5,10 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v13.17.7 - _September 15, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v13.17.6 - _September 1, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/contract-wrappers",
|
||||
"version": "13.17.7",
|
||||
"version": "13.17.6",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -55,14 +55,14 @@
|
||||
"typescript": "4.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/assert": "^3.0.29",
|
||||
"@0x/base-contract": "^6.4.2",
|
||||
"@0x/assert": "^3.0.27",
|
||||
"@0x/base-contract": "^6.4.0",
|
||||
"@0x/contract-addresses": "^6.7.0",
|
||||
"@0x/json-schemas": "^6.3.0",
|
||||
"@0x/types": "^3.3.4",
|
||||
"@0x/utils": "^6.4.4",
|
||||
"@0x/web3-wrapper": "^7.6.0",
|
||||
"ethereum-types": "^3.6.0",
|
||||
"@0x/json-schemas": "^6.1.3",
|
||||
"@0x/types": "^3.3.3",
|
||||
"@0x/utils": "^6.4.3",
|
||||
"@0x/web3-wrapper": "^7.5.3",
|
||||
"ethereum-types": "^3.5.0",
|
||||
"ethers": "~4.0.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
||||
@@ -1,22 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1631710679,
|
||||
"version": "8.1.6",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1631120757,
|
||||
"version": "8.1.5",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Dependencies updated"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1630459879,
|
||||
"version": "8.1.4",
|
||||
|
||||
@@ -5,14 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v8.1.6 - _September 15, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v8.1.5 - _September 8, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
## v8.1.4 - _September 1, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/migrations",
|
||||
"version": "8.1.6",
|
||||
"version": "8.1.4",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -48,10 +48,10 @@
|
||||
"registry": "git@github.com:0xProject/gitpkg-registry.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@0x/dev-utils": "^4.2.9",
|
||||
"@0x/dev-utils": "^4.2.7",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.4",
|
||||
"@0x/types": "^3.3.4",
|
||||
"@0x/types": "^3.3.3",
|
||||
"@types/yargs": "^11.0.0",
|
||||
"chai": "^4.0.1",
|
||||
"dirty-chai": "^2.0.1",
|
||||
@@ -67,29 +67,29 @@
|
||||
"yargs": "^10.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.4.2",
|
||||
"@0x/base-contract": "^6.4.0",
|
||||
"@0x/contract-addresses": "^6.7.0",
|
||||
"@0x/contracts-asset-proxy": "^3.7.19",
|
||||
"@0x/contracts-coordinator": "^3.1.38",
|
||||
"@0x/contracts-dev-utils": "^1.3.36",
|
||||
"@0x/contracts-erc1155": "^2.1.37",
|
||||
"@0x/contracts-erc20": "^3.3.20",
|
||||
"@0x/contracts-erc20": "^3.3.18",
|
||||
"@0x/contracts-erc721": "^3.1.37",
|
||||
"@0x/contracts-exchange": "^3.2.38",
|
||||
"@0x/contracts-exchange-forwarder": "^4.2.38",
|
||||
"@0x/contracts-extensions": "^6.2.32",
|
||||
"@0x/contracts-multisig": "^4.1.38",
|
||||
"@0x/contracts-staking": "^2.0.45",
|
||||
"@0x/contracts-utils": "^4.8.1",
|
||||
"@0x/contracts-zero-ex": "^0.28.5",
|
||||
"@0x/sol-compiler": "^4.7.5",
|
||||
"@0x/subproviders": "^6.6.0",
|
||||
"@0x/typescript-typings": "^5.2.1",
|
||||
"@0x/utils": "^6.4.4",
|
||||
"@0x/web3-wrapper": "^7.6.0",
|
||||
"@0x/contracts-utils": "^4.7.18",
|
||||
"@0x/contracts-zero-ex": "^0.28.3",
|
||||
"@0x/sol-compiler": "^4.7.3",
|
||||
"@0x/subproviders": "^6.5.3",
|
||||
"@0x/typescript-typings": "^5.2.0",
|
||||
"@0x/utils": "^6.4.3",
|
||||
"@0x/web3-wrapper": "^7.5.3",
|
||||
"@ledgerhq/hw-app-eth": "^4.3.0",
|
||||
"@types/web3-provider-engine": "^14.0.0",
|
||||
"ethereum-types": "^3.6.0",
|
||||
"ethereum-types": "^3.5.0",
|
||||
"ethereumjs-util": "^7.1.0",
|
||||
"ethers": "~4.0.4",
|
||||
"lodash": "^4.17.11"
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
[
|
||||
{
|
||||
"version": "1.9.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add 'TreasuryVote' class"
|
||||
}
|
||||
],
|
||||
"timestamp": 1631710679
|
||||
},
|
||||
{
|
||||
"timestamp": 1630459879,
|
||||
"version": "1.8.4",
|
||||
|
||||
@@ -5,10 +5,6 @@ Edit the package's CHANGELOG.json file only.
|
||||
|
||||
CHANGELOG
|
||||
|
||||
## v1.9.0 - _September 15, 2021_
|
||||
|
||||
* Add 'TreasuryVote' class
|
||||
|
||||
## v1.8.4 - _September 1, 2021_
|
||||
|
||||
* Dependencies updated
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@0x/protocol-utils",
|
||||
"version": "1.9.0",
|
||||
"version": "1.8.4",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
@@ -41,17 +41,17 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/protocol/tree/main/packages/protocol-utils",
|
||||
"devDependencies": {
|
||||
"@0x/dev-utils": "^4.2.9",
|
||||
"@0x/dev-utils": "^4.2.7",
|
||||
"@0x/ts-doc-gen": "^0.0.28",
|
||||
"@0x/tslint-config": "^4.1.4",
|
||||
"@0x/types": "^3.3.4",
|
||||
"@0x/typescript-typings": "^5.2.1",
|
||||
"@0x/types": "^3.3.3",
|
||||
"@0x/typescript-typings": "^5.2.0",
|
||||
"@types/bn.js": "^4.11.0",
|
||||
"@types/lodash": "4.14.104",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "12.12.54",
|
||||
"@types/web3-provider-engine": "^14.0.0",
|
||||
"ethereum-types": "^3.6.0",
|
||||
"ethereum-types": "^3.5.0",
|
||||
"mocha": "^6.2.0",
|
||||
"npm-run-all": "^4.1.2",
|
||||
"shx": "^0.2.2",
|
||||
@@ -62,13 +62,13 @@
|
||||
"web3-provider-engine": "14.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@0x/assert": "^3.0.29",
|
||||
"@0x/assert": "^3.0.27",
|
||||
"@0x/contract-addresses": "^6.7.0",
|
||||
"@0x/contract-wrappers": "^13.17.7",
|
||||
"@0x/json-schemas": "^6.3.0",
|
||||
"@0x/subproviders": "^6.6.0",
|
||||
"@0x/utils": "^6.4.4",
|
||||
"@0x/web3-wrapper": "^7.6.0",
|
||||
"@0x/contract-wrappers": "^13.17.6",
|
||||
"@0x/json-schemas": "^6.1.3",
|
||||
"@0x/subproviders": "^6.5.3",
|
||||
"@0x/utils": "^6.4.3",
|
||||
"@0x/web3-wrapper": "^7.5.3",
|
||||
"chai": "^4.0.1",
|
||||
"ethereumjs-util": "^7.0.10",
|
||||
"ethers": "~4.0.4",
|
||||
|
||||
@@ -9,4 +9,3 @@ export * from './signature_utils';
|
||||
export * from './transformer_utils';
|
||||
export * from './constants';
|
||||
export * from './vip_utils';
|
||||
export * from './treasury_votes';
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
import { BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
|
||||
import { ZERO } from './constants';
|
||||
import { EIP712_DOMAIN_PARAMETERS, getTypeHash } from './eip712_utils';
|
||||
import { eip712SignHashWithKey, Signature } from './signature_utils';
|
||||
|
||||
const VOTE_DEFAULT_VALUES = {
|
||||
proposalId: ZERO,
|
||||
support: false,
|
||||
operatedPoolIds: [] as string[],
|
||||
chainId: 1,
|
||||
version: '1.0.0',
|
||||
verifyingContract: NULL_ADDRESS,
|
||||
};
|
||||
|
||||
export type TreasuryVoteFields = typeof VOTE_DEFAULT_VALUES;
|
||||
|
||||
export class TreasuryVote {
|
||||
public static readonly CONTRACT_NAME = 'Zrx Treasury';
|
||||
|
||||
public static readonly MESSAGE_STRUCT_NAME = 'TreasuryVote';
|
||||
public static readonly MESSAGE_STRUCT_ABI = [
|
||||
{ type: 'uint256', name: 'proposalId' },
|
||||
{ type: 'bool', name: 'support' },
|
||||
{ type: 'bytes32[]', name: 'operatedPoolIds' },
|
||||
];
|
||||
public static readonly MESSAGE_TYPE_HASH = getTypeHash(
|
||||
TreasuryVote.MESSAGE_STRUCT_NAME,
|
||||
TreasuryVote.MESSAGE_STRUCT_ABI,
|
||||
);
|
||||
|
||||
public static readonly DOMAIN_STRUCT_NAME = 'EIP712Domain';
|
||||
public static readonly DOMAIN_TYPE_HASH = getTypeHash(TreasuryVote.DOMAIN_STRUCT_NAME, EIP712_DOMAIN_PARAMETERS);
|
||||
|
||||
public proposalId: BigNumber;
|
||||
public support: boolean;
|
||||
public operatedPoolIds: string[];
|
||||
public chainId: number;
|
||||
public version: string;
|
||||
public verifyingContract: string;
|
||||
|
||||
constructor(fields: Partial<TreasuryVoteFields> = {}) {
|
||||
const _fields = { ...VOTE_DEFAULT_VALUES, ...fields };
|
||||
this.proposalId = _fields.proposalId;
|
||||
this.support = _fields.support;
|
||||
this.operatedPoolIds = _fields.operatedPoolIds;
|
||||
this.chainId = _fields.chainId;
|
||||
this.version = _fields.version;
|
||||
this.verifyingContract = _fields.verifyingContract;
|
||||
}
|
||||
|
||||
public getDomainHash(): string {
|
||||
return hexUtils.hash(
|
||||
hexUtils.concat(
|
||||
hexUtils.leftPad(TreasuryVote.DOMAIN_TYPE_HASH),
|
||||
hexUtils.hash(hexUtils.toHex(Buffer.from(TreasuryVote.CONTRACT_NAME))),
|
||||
hexUtils.leftPad(this.chainId),
|
||||
hexUtils.hash(hexUtils.toHex(Buffer.from(this.version))),
|
||||
hexUtils.leftPad(this.verifyingContract),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public getStructHash(): string {
|
||||
return hexUtils.hash(
|
||||
hexUtils.concat(
|
||||
hexUtils.leftPad(TreasuryVote.MESSAGE_TYPE_HASH),
|
||||
hexUtils.leftPad(this.proposalId),
|
||||
hexUtils.leftPad(this.support ? 1 : 0),
|
||||
hexUtils.hash(
|
||||
ethUtil.toBuffer(hexUtils.concat(...this.operatedPoolIds.map(id => hexUtils.leftPad(id)))),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public getEIP712Hash(): string {
|
||||
return hexUtils.hash(hexUtils.toHex(hexUtils.concat('0x1901', this.getDomainHash(), this.getStructHash())));
|
||||
}
|
||||
|
||||
public getSignatureWithKey(privateKey: string): Signature {
|
||||
return eip712SignHashWithKey(this.getEIP712Hash(), privateKey);
|
||||
}
|
||||
}
|
||||
276
yarn.lock
276
yarn.lock
@@ -643,20 +643,19 @@
|
||||
npmlog "^4.1.2"
|
||||
write-file-atomic "^2.3.0"
|
||||
|
||||
"@0x/abi-gen@^5.6.2":
|
||||
version "5.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@0x/abi-gen/-/abi-gen-5.6.2.tgz#a31b26b93b061ceb8513424d622119c78b3ed0e9"
|
||||
integrity sha512-G+B9/VEfsOc8IOgUgkIdFiC+0RNg1DTR921WOxOxcvLsls9m9lBudl7hFrU03N1QdbFFP08e+HDj1kS2Q+SzEQ==
|
||||
"@0x/abi-gen@^5.6.0":
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@0x/abi-gen/-/abi-gen-5.6.0.tgz#2b022efe77a35f5589624633d880d794d0a16bde"
|
||||
dependencies:
|
||||
"@0x/types" "^3.3.4"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/utils" "^6.4.4"
|
||||
"@0x/types" "^3.3.3"
|
||||
"@0x/typescript-typings" "^5.2.0"
|
||||
"@0x/utils" "^6.4.3"
|
||||
"@types/node" "12.12.54"
|
||||
"@types/toposort" "^2.0.1"
|
||||
chalk "^2.3.0"
|
||||
change-case "^3.0.2"
|
||||
cli-format "^3.0.9"
|
||||
ethereum-types "^3.6.0"
|
||||
ethereum-types "^3.5.0"
|
||||
glob "^7.1.2"
|
||||
handlebars "^4.1.2"
|
||||
lodash "^4.17.11"
|
||||
@@ -677,18 +676,6 @@
|
||||
lodash "^4.17.11"
|
||||
valid-url "^1.0.9"
|
||||
|
||||
"@0x/assert@^3.0.29":
|
||||
version "3.0.29"
|
||||
resolved "https://registry.yarnpkg.com/@0x/assert/-/assert-3.0.29.tgz#604e415b943140a1577c9389b04766909a60b589"
|
||||
integrity sha512-EiF8TwCtM17KFcLy2FYVzu3+7K51VyUNs9ZQ/Wf8tWDeTWrIh1ixKGsNtRnL9sR5SPqOLwKR3lbGn+zPlxw+Yw==
|
||||
dependencies:
|
||||
"@0x/json-schemas" "^6.3.0"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/utils" "^6.4.4"
|
||||
"@types/node" "12.12.54"
|
||||
lodash "^4.17.11"
|
||||
valid-url "^1.0.9"
|
||||
|
||||
"@0x/assert@^3.0.6":
|
||||
version "3.0.21"
|
||||
resolved "https://registry.yarnpkg.com/@0x/assert/-/assert-3.0.21.tgz#b385868d1833625912fd9173a2477be5a4090aed"
|
||||
@@ -717,24 +704,6 @@
|
||||
js-sha3 "^0.7.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
"@0x/base-contract@^6.4.2":
|
||||
version "6.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@0x/base-contract/-/base-contract-6.4.2.tgz#d87cb5416613d29d2ec71c60d4a7c6cdd5c48694"
|
||||
integrity sha512-lcmsXGJ2ImiO1tJoWefYiQ8/WRSdQ4BPA8XulYqVQ4su6PYjLa1XvU91zM779QrIPeRo8fL7FUvGE7CkyG/gwA==
|
||||
dependencies:
|
||||
"@0x/assert" "^3.0.29"
|
||||
"@0x/json-schemas" "^6.3.0"
|
||||
"@0x/utils" "^6.4.4"
|
||||
"@0x/web3-wrapper" "^7.6.0"
|
||||
"@types/node" "12.12.54"
|
||||
ethereumjs-account "^3.0.0"
|
||||
ethereumjs-blockstream "^7.0.0"
|
||||
ethereumjs-util "^7.1.0"
|
||||
ethereumjs-vm "^4.2.0"
|
||||
ethers "~4.0.4"
|
||||
js-sha3 "^0.7.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
"@0x/contracts-asset-proxy@^3.7.19":
|
||||
version "3.7.19"
|
||||
resolved "https://registry.yarnpkg.com/@0x/contracts-asset-proxy/-/contracts-asset-proxy-3.7.19.tgz#ee621a233f4d77b439c74c5b8d70db2e1ed001c4"
|
||||
@@ -835,18 +804,17 @@
|
||||
"@0x/typescript-typings" "^5.2.0"
|
||||
ethereum-types "^3.5.0"
|
||||
|
||||
"@0x/contracts-gen@^2.0.40":
|
||||
version "2.0.40"
|
||||
resolved "https://registry.yarnpkg.com/@0x/contracts-gen/-/contracts-gen-2.0.40.tgz#526c25991125b5a4deb745e470b3c64cd8673095"
|
||||
integrity sha512-Luj6R4DtPI7KHr3tUSdarudNiySd6GY1mvfhu8566K76oq4aK1no1hf0pyvy9tQLJDViNePP8Ad5KcEmC89sAg==
|
||||
"@0x/contracts-gen@^2.0.38":
|
||||
version "2.0.38"
|
||||
resolved "https://registry.yarnpkg.com/@0x/contracts-gen/-/contracts-gen-2.0.38.tgz#6f2977e2bcb299b5e8a32f45d7eca73d19e34c50"
|
||||
dependencies:
|
||||
"@0x/sol-compiler" "^4.7.5"
|
||||
"@0x/sol-resolver" "^3.1.9"
|
||||
"@0x/types" "^3.3.4"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/utils" "^6.4.4"
|
||||
"@0x/sol-compiler" "^4.7.3"
|
||||
"@0x/sol-resolver" "^3.1.8"
|
||||
"@0x/types" "^3.3.3"
|
||||
"@0x/typescript-typings" "^5.2.0"
|
||||
"@0x/utils" "^6.4.3"
|
||||
"@types/node" "12.12.54"
|
||||
ethereum-types "^3.6.0"
|
||||
ethereum-types "^3.5.0"
|
||||
lodash "^4.17.11"
|
||||
mkdirp "^0.5.1"
|
||||
prettier "^1.16.3"
|
||||
@@ -871,10 +839,9 @@
|
||||
ethereum-types "^3.5.0"
|
||||
ethereumjs-util "^7.0.10"
|
||||
|
||||
"@0x/contracts-zero-ex@^0.27.1":
|
||||
"@0x/contracts-zero-ex@^0.27.0":
|
||||
version "0.27.1"
|
||||
resolved "https://registry.yarnpkg.com/@0x/contracts-zero-ex/-/contracts-zero-ex-0.27.1.tgz#968fe9d8134972cb464f7c4a33c4e4089ba9218e"
|
||||
integrity sha512-IDc0pmMtl/92hkhOqlu+dDyIvLtGtwjjE/kdS6x+jwOyNG8sn5sbkwZ3u3PbHk72dND7E0I7BBY9VEXTB1PY/Q==
|
||||
dependencies:
|
||||
"@0x/base-contract" "^6.4.0"
|
||||
"@0x/protocol-utils" "^1.8.1"
|
||||
@@ -886,23 +853,22 @@
|
||||
ethereum-types "^3.5.0"
|
||||
ethereumjs-util "^7.0.10"
|
||||
|
||||
"@0x/dev-utils@^4.2.9":
|
||||
version "4.2.9"
|
||||
resolved "https://registry.yarnpkg.com/@0x/dev-utils/-/dev-utils-4.2.9.tgz#b048b139b0055ef3702682c42ccc2a3788a49f5d"
|
||||
integrity sha512-juIjVvky0umt7Tmzhz2PF7e7pQEe1hbrV2XyB5tocRQVAsTD+TuwTG9VVKULQUptX+B/mF1mjb3WwEQV6y/yTQ==
|
||||
"@0x/dev-utils@^4.2.7":
|
||||
version "4.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@0x/dev-utils/-/dev-utils-4.2.7.tgz#9c85a134cace5a423a75221241fd687df81f3bbc"
|
||||
dependencies:
|
||||
"@0x/subproviders" "^6.6.0"
|
||||
"@0x/types" "^3.3.4"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/utils" "^6.4.4"
|
||||
"@0x/web3-wrapper" "^7.6.0"
|
||||
"@0x/subproviders" "^6.5.3"
|
||||
"@0x/types" "^3.3.3"
|
||||
"@0x/typescript-typings" "^5.2.0"
|
||||
"@0x/utils" "^6.4.3"
|
||||
"@0x/web3-wrapper" "^7.5.3"
|
||||
"@types/node" "12.12.54"
|
||||
"@types/web3-provider-engine" "^14.0.0"
|
||||
chai "^4.0.1"
|
||||
chai-as-promised "^7.1.0"
|
||||
chai-bignumber "^3.0.0"
|
||||
dirty-chai "^2.0.1"
|
||||
ethereum-types "^3.6.0"
|
||||
ethereum-types "^3.5.0"
|
||||
lodash "^4.17.11"
|
||||
web3-provider-engine "14.0.6"
|
||||
|
||||
@@ -924,16 +890,6 @@
|
||||
ajv "^6.12.5"
|
||||
lodash.values "^4.3.0"
|
||||
|
||||
"@0x/json-schemas@^6.3.0":
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-6.3.0.tgz#b7addf8167af492f6667561caa9a62b3ec567696"
|
||||
integrity sha512-cygnTxvJhLYcDeI05Olp4CN0BKQRs2rC3L0gRCU+mV/IMDNYlkKqNluHmzoHLBleN55uLZZZybSLOsbE5HfIlQ==
|
||||
dependencies:
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@types/node" "12.12.54"
|
||||
ajv "^6.12.5"
|
||||
lodash.values "^4.3.0"
|
||||
|
||||
"@0x/mesh-rpc-client@^9.4.2":
|
||||
version "9.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@0x/mesh-rpc-client/-/mesh-rpc-client-9.4.2.tgz#6f9690fb1cb37fb0c2fd3907241af0e543c78451"
|
||||
@@ -988,10 +944,9 @@
|
||||
ethers "~4.0.4"
|
||||
lodash "^4.17.11"
|
||||
|
||||
"@0x/quote-server@^6.0.6":
|
||||
version "6.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@0x/quote-server/-/quote-server-6.0.6.tgz#0f0bf50647efc4bff039a491689974af7e8c5776"
|
||||
integrity sha512-ubugDwCFDhOv8R8LWO4Z9BmWfm/KjbB92bg1nEHw2HzosOk1rLkQWnPCJGqbMzxHlt3EtLxXPrrZE2IxWBKgwQ==
|
||||
"@0x/quote-server@^6.0.2":
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@0x/quote-server/-/quote-server-6.0.2.tgz#cb99e00c737e0f97a2a32bc7e7be6db65243c3af"
|
||||
dependencies:
|
||||
"@0x/json-schemas" "^6.0.1"
|
||||
"@0x/order-utils" "^10.2.4"
|
||||
@@ -1002,24 +957,23 @@
|
||||
express-async-handler "^1.1.4"
|
||||
http-status-codes "^1.4.0"
|
||||
|
||||
"@0x/sol-compiler@^4.7.5":
|
||||
version "4.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-compiler/-/sol-compiler-4.7.5.tgz#f744f836786f44747cfd23eb167067ce6f348136"
|
||||
integrity sha512-vVsMNFLsR7ORuriZXCWloEhDZh3loaTkiFgFI3zTne7wOCwyMntZkgA7uij/iyOGrZW0XEbxAA+QjAYenroRfQ==
|
||||
"@0x/sol-compiler@^4.7.3":
|
||||
version "4.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-compiler/-/sol-compiler-4.7.3.tgz#d994661bc9c06a0a63b0e2f77ee6511d3cef488e"
|
||||
dependencies:
|
||||
"@0x/assert" "^3.0.29"
|
||||
"@0x/json-schemas" "^6.3.0"
|
||||
"@0x/sol-resolver" "^3.1.9"
|
||||
"@0x/types" "^3.3.4"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/utils" "^6.4.4"
|
||||
"@0x/web3-wrapper" "^7.6.0"
|
||||
"@0x/assert" "^3.0.27"
|
||||
"@0x/json-schemas" "^6.1.3"
|
||||
"@0x/sol-resolver" "^3.1.8"
|
||||
"@0x/types" "^3.3.3"
|
||||
"@0x/typescript-typings" "^5.2.0"
|
||||
"@0x/utils" "^6.4.3"
|
||||
"@0x/web3-wrapper" "^7.5.3"
|
||||
"@types/node" "12.12.54"
|
||||
"@types/yargs" "^11.0.0"
|
||||
chalk "^2.3.0"
|
||||
chokidar "^3.0.2"
|
||||
ethereum-types "^3.6.0"
|
||||
ethereumjs-util "^7.1.0"
|
||||
ethereum-types "^3.5.0"
|
||||
ethereumjs-util "^7.0.10"
|
||||
lodash "^4.17.11"
|
||||
mkdirp "^0.5.1"
|
||||
pluralize "^7.0.0"
|
||||
@@ -1031,79 +985,74 @@
|
||||
web3-eth-abi "^1.0.0-beta.24"
|
||||
yargs "^10.0.3"
|
||||
|
||||
"@0x/sol-coverage@^4.0.39":
|
||||
version "4.0.39"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-coverage/-/sol-coverage-4.0.39.tgz#27db909a3f35c625bbf271fa7ecd693eb880ed53"
|
||||
integrity sha512-mARTgkNX4xkY8UVeYO1oQ0+iY9OJyeRHZbuiWizdeCRuoZth7qk8F1xbywZTCPyo6Pa4zmusi7poKRfHIFTFHA==
|
||||
"@0x/sol-coverage@^4.0.37":
|
||||
version "4.0.37"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-coverage/-/sol-coverage-4.0.37.tgz#951363f1497cc65edf9bc76f37ac7824667e2c2b"
|
||||
dependencies:
|
||||
"@0x/sol-tracing-utils" "^7.2.5"
|
||||
"@0x/subproviders" "^6.6.0"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/sol-tracing-utils" "^7.2.3"
|
||||
"@0x/subproviders" "^6.5.3"
|
||||
"@0x/typescript-typings" "^5.2.0"
|
||||
"@types/minimatch" "^3.0.3"
|
||||
"@types/node" "12.12.54"
|
||||
ethereum-types "^3.6.0"
|
||||
ethereum-types "^3.5.0"
|
||||
lodash "^4.17.11"
|
||||
minimatch "^3.0.4"
|
||||
web3-provider-engine "14.0.6"
|
||||
|
||||
"@0x/sol-profiler@^4.1.29":
|
||||
version "4.1.29"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-profiler/-/sol-profiler-4.1.29.tgz#e77e0ae50541e8acaf7cecb5378a60efd4282f11"
|
||||
integrity sha512-4CbrNan9xF3auv0ZwjsoajgpqLO23eqcq1u9seSVriNs5IGxEOq4U5xxofvFIMaS0NQXnHJobuUT2qRayBbgkw==
|
||||
"@0x/sol-profiler@^4.1.27":
|
||||
version "4.1.27"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-profiler/-/sol-profiler-4.1.27.tgz#2bd14882dd204a7465b494149877daa16d86208d"
|
||||
dependencies:
|
||||
"@0x/sol-tracing-utils" "^7.2.5"
|
||||
"@0x/subproviders" "^6.6.0"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/utils" "^6.4.4"
|
||||
"@0x/sol-tracing-utils" "^7.2.3"
|
||||
"@0x/subproviders" "^6.5.3"
|
||||
"@0x/typescript-typings" "^5.2.0"
|
||||
"@0x/utils" "^6.4.3"
|
||||
"@types/node" "12.12.54"
|
||||
ethereum-types "^3.6.0"
|
||||
ethereumjs-util "^7.1.0"
|
||||
ethereum-types "^3.5.0"
|
||||
ethereumjs-util "^7.0.10"
|
||||
lodash "^4.17.11"
|
||||
web3-provider-engine "14.0.6"
|
||||
|
||||
"@0x/sol-resolver@^3.1.9":
|
||||
version "3.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-resolver/-/sol-resolver-3.1.9.tgz#525c545c4ff4d0ff2ff99e433b2405778abe0693"
|
||||
integrity sha512-N+GxAqtHzEgVsnj9k4yeE7xRqE2ymR+yo98j0s2VC8icjecVqm6LtqQpEpdPULEg20vA0aPdU/XY2q0xiCDpLg==
|
||||
"@0x/sol-resolver@^3.1.8":
|
||||
version "3.1.8"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-resolver/-/sol-resolver-3.1.8.tgz#eaaaf17052e88213e55daf2c6e39a585cc16fa0a"
|
||||
dependencies:
|
||||
"@0x/types" "^3.3.4"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/types" "^3.3.3"
|
||||
"@0x/typescript-typings" "^5.2.0"
|
||||
"@types/node" "12.12.54"
|
||||
lodash "^4.17.11"
|
||||
|
||||
"@0x/sol-trace@^3.0.39":
|
||||
version "3.0.39"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-trace/-/sol-trace-3.0.39.tgz#caca4fbf049eda25185c09ab00c23cf37d44d9a2"
|
||||
integrity sha512-Dg+jPjCnSmWL4t/tq/kQY8NOnAWy/g4HjFQYyL6uz8ioJ4gvCCV+2UADATb2OA7bqrvtbADJrw7icJ+/laqXuA==
|
||||
"@0x/sol-trace@^3.0.37":
|
||||
version "3.0.37"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-trace/-/sol-trace-3.0.37.tgz#915a1c7c4869f9a95994fdb24878997d5bc39450"
|
||||
dependencies:
|
||||
"@0x/sol-tracing-utils" "^7.2.5"
|
||||
"@0x/subproviders" "^6.6.0"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/sol-tracing-utils" "^7.2.3"
|
||||
"@0x/subproviders" "^6.5.3"
|
||||
"@0x/typescript-typings" "^5.2.0"
|
||||
"@types/node" "12.12.54"
|
||||
chalk "^2.3.0"
|
||||
ethereum-types "^3.6.0"
|
||||
ethereumjs-util "^7.1.0"
|
||||
ethereum-types "^3.5.0"
|
||||
ethereumjs-util "^7.0.10"
|
||||
lodash "^4.17.11"
|
||||
loglevel "^1.6.1"
|
||||
web3-provider-engine "14.0.6"
|
||||
|
||||
"@0x/sol-tracing-utils@^7.2.5":
|
||||
version "7.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-tracing-utils/-/sol-tracing-utils-7.2.5.tgz#19ced9ecf6811dab4133ea9acf4dfdd0987b14fd"
|
||||
integrity sha512-ptffYU/KigOipFGwxWHqToQ/pbkbCyODBcxVTKeEW4MFlHeRMDRHypDM13VFAyAxqQwzvOfk22xeuLVUsKwPVQ==
|
||||
"@0x/sol-tracing-utils@^7.2.3":
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@0x/sol-tracing-utils/-/sol-tracing-utils-7.2.3.tgz#2a24969943315af4f86ceab12ad8bc34433069e5"
|
||||
dependencies:
|
||||
"@0x/dev-utils" "^4.2.9"
|
||||
"@0x/sol-compiler" "^4.7.5"
|
||||
"@0x/sol-resolver" "^3.1.9"
|
||||
"@0x/subproviders" "^6.6.0"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/utils" "^6.4.4"
|
||||
"@0x/web3-wrapper" "^7.6.0"
|
||||
"@0x/dev-utils" "^4.2.7"
|
||||
"@0x/sol-compiler" "^4.7.3"
|
||||
"@0x/sol-resolver" "^3.1.8"
|
||||
"@0x/subproviders" "^6.5.3"
|
||||
"@0x/typescript-typings" "^5.2.0"
|
||||
"@0x/utils" "^6.4.3"
|
||||
"@0x/web3-wrapper" "^7.5.3"
|
||||
"@types/node" "12.12.54"
|
||||
"@types/solidity-parser-antlr" "^0.2.3"
|
||||
chalk "^2.3.0"
|
||||
ethereum-types "^3.6.0"
|
||||
ethereumjs-util "^7.1.0"
|
||||
ethereum-types "^3.5.0"
|
||||
ethereumjs-util "^7.0.10"
|
||||
ethers "~4.0.4"
|
||||
glob "^7.1.2"
|
||||
istanbul "^0.4.5"
|
||||
@@ -1144,36 +1093,6 @@
|
||||
optionalDependencies:
|
||||
"@ledgerhq/hw-transport-node-hid" "^4.3.0"
|
||||
|
||||
"@0x/subproviders@^6.6.0":
|
||||
version "6.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-6.6.0.tgz#1743d44ae5e2be9ec48caddbf0f1a580f1672d32"
|
||||
integrity sha512-fQ4efPH/io+TAYEsZuYj9YpoAy0fGWx8QZaWeNstxFT2Miph2aq4Bh+GGrQcXSjNx+prgdBDAGePJvtGP8Qs3Q==
|
||||
dependencies:
|
||||
"@0x/assert" "^3.0.29"
|
||||
"@0x/types" "^3.3.4"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/utils" "^6.4.4"
|
||||
"@0x/web3-wrapper" "^7.6.0"
|
||||
"@ethereumjs/common" "^2.4.0"
|
||||
"@ethereumjs/tx" "^3.3.0"
|
||||
"@ledgerhq/hw-app-eth" "^4.3.0"
|
||||
"@ledgerhq/hw-transport-u2f" "4.24.0"
|
||||
"@types/hdkey" "^0.7.0"
|
||||
"@types/node" "12.12.54"
|
||||
"@types/web3-provider-engine" "^14.0.0"
|
||||
bip39 "^2.5.0"
|
||||
bn.js "^4.11.8"
|
||||
ethereum-types "^3.6.0"
|
||||
ethereumjs-util "^7.1.0"
|
||||
ganache-core "^2.13.2"
|
||||
hdkey "^0.7.1"
|
||||
json-rpc-error "2.0.0"
|
||||
lodash "^4.17.11"
|
||||
semaphore-async-await "^1.5.1"
|
||||
web3-provider-engine "14.0.6"
|
||||
optionalDependencies:
|
||||
"@ledgerhq/hw-transport-node-hid" "^4.3.0"
|
||||
|
||||
"@0x/ts-doc-gen@^0.0.28":
|
||||
version "0.0.28"
|
||||
resolved "https://registry.yarnpkg.com/@0x/ts-doc-gen/-/ts-doc-gen-0.0.28.tgz#075f53268e99ece6448515a3347b1d51fe92365f"
|
||||
@@ -1365,21 +1284,6 @@
|
||||
ethers "~4.0.4"
|
||||
lodash "^4.17.11"
|
||||
|
||||
"@0x/web3-wrapper@^7.6.0":
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@0x/web3-wrapper/-/web3-wrapper-7.6.0.tgz#34ae5e32affc02ed425c7bb3402a26fd7880c999"
|
||||
integrity sha512-yxvTT/w5PFfnbKZ9Xvt412fyhVfiNQ0ugFbJYr+X+Xye+Q9vZzzbfc2a3bJSO7w/HkZx7vND071F/jtqU1JsEg==
|
||||
dependencies:
|
||||
"@0x/assert" "^3.0.29"
|
||||
"@0x/json-schemas" "^6.3.0"
|
||||
"@0x/typescript-typings" "^5.2.1"
|
||||
"@0x/utils" "^6.4.4"
|
||||
"@types/node" "12.12.54"
|
||||
ethereum-types "^3.6.0"
|
||||
ethereumjs-util "^7.1.0"
|
||||
ethers "~4.0.4"
|
||||
lodash "^4.17.11"
|
||||
|
||||
"@0xproject/npm-cli-login@^0.0.11":
|
||||
version "0.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@0xproject/npm-cli-login/-/npm-cli-login-0.0.11.tgz#3f1ec06112ce62aad300ff0575358f68aeecde2e"
|
||||
@@ -1449,14 +1353,6 @@
|
||||
crc-32 "^1.2.0"
|
||||
ethereumjs-util "^7.0.9"
|
||||
|
||||
"@ethereumjs/common@^2.4.0":
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.4.0.tgz#2d67f6e6ba22246c5c89104e6b9a119fb3039766"
|
||||
integrity sha512-UdkhFWzWcJCZVsj1O/H8/oqj/0RVYjLc1OhPjBrQdALAkQHpCp8xXI4WLnuGTADqTdJZww0NtgwG+TRPkXt27w==
|
||||
dependencies:
|
||||
crc-32 "^1.2.0"
|
||||
ethereumjs-util "^7.1.0"
|
||||
|
||||
"@ethereumjs/tx@^3.1.3":
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.1.4.tgz#04cf9e9406da5f04a1a26c458744641f4b4b8dd0"
|
||||
@@ -1464,14 +1360,6 @@
|
||||
"@ethereumjs/common" "^2.2.0"
|
||||
ethereumjs-util "^7.0.10"
|
||||
|
||||
"@ethereumjs/tx@^3.3.0":
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.0.tgz#14ed1b7fa0f28e1cd61e3ecbdab824205f6a4378"
|
||||
integrity sha512-yTwEj2lVzSMgE6Hjw9Oa1DZks/nKTWM8Wn4ykDNapBPua2f4nXO3qKnni86O6lgDj5fVNRqbDsD0yy7/XNGDEA==
|
||||
dependencies:
|
||||
"@ethereumjs/common" "^2.4.0"
|
||||
ethereumjs-util "^7.1.0"
|
||||
|
||||
"@ethersproject/abi@5.0.0-beta.153":
|
||||
version "5.0.0-beta.153"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee"
|
||||
|
||||
Reference in New Issue
Block a user