@cowprotocol/contracts
Advanced tools
Comparing version 1.5.0 to 1.6.0
@@ -21,2 +21,6 @@ { | ||
"transactionHash": "0xad2b992f7363e5eb8523a7034a7d36a311485f126db9938d4847cc38d2d86b86" | ||
}, | ||
"42161": { | ||
"address": "0x9E7Ae8Bdba9AA346739792d219a808884996Db67", | ||
"transactionHash": "0x084c7e025a5064a2649adbce79f94f23666c1c7e4c7ce02466412524502097ad" | ||
} | ||
@@ -44,2 +48,6 @@ }, | ||
"transactionHash": "0x73c54c75b3f382304f3adf33e3876c8999fb10df786d4a902733369251033cd1" | ||
}, | ||
"42161": { | ||
"address": "0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE", | ||
"transactionHash": "0xe994adff141a2e72bd9dab3eb7b3480637013bdfb1aa42c62d9d6c90de091237" | ||
} | ||
@@ -67,2 +75,6 @@ }, | ||
"transactionHash": "0x73c54c75b3f382304f3adf33e3876c8999fb10df786d4a902733369251033cd1" | ||
}, | ||
"42161": { | ||
"address": "0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE", | ||
"transactionHash": "0xe994adff141a2e72bd9dab3eb7b3480637013bdfb1aa42c62d9d6c90de091237" | ||
} | ||
@@ -90,2 +102,6 @@ }, | ||
"transactionHash": "0x6bba22a00ffcff6bca79aced546e18d2a5a4f4e484a4e4dbafab13daf42f718d" | ||
}, | ||
"42161": { | ||
"address": "0x9008D19f58AAbD9eD0D60971565AA8510560ab41", | ||
"transactionHash": "0x240486f35ebf42ea69b2b3f1569d587c18c87f98c0ec997bef7d18182ca4c38c" | ||
} | ||
@@ -113,4 +129,8 @@ }, | ||
"transactionHash": "0x6bba22a00ffcff6bca79aced546e18d2a5a4f4e484a4e4dbafab13daf42f718d" | ||
}, | ||
"42161": { | ||
"address": "0xC92E8bdf79f0507f65a392b0ab4667716BFE0110", | ||
"transactionHash": "0x240486f35ebf42ea69b2b3f1569d587c18c87f98c0ec997bef7d18182ca4c38c" | ||
} | ||
} | ||
} | ||
} |
{ | ||
"name": "@cowprotocol/contracts", | ||
"version": "1.5.0", | ||
"version": "1.6.0", | ||
"license": "LGPL-3.0-or-later", | ||
@@ -5,0 +5,0 @@ "repository": { |
@@ -60,8 +60,2 @@ # CoW Protocol | ||
Contracts deployment (including contract verification) is run automatically with GitHub Actions. The deployment process is triggered manually. | ||
Maintainers of this repository can deploy a new version of the contract in the "Actions" tab, "Deploy CoW Protocol contracts", "Run workflow". The target branch can be selected before running. | ||
A successful workflow results in a new PR asking to merge the deployment artifacts into the main branch. | ||
Contracts can also be deployed and verified manually as follows. | ||
### Deploying Contracts | ||
@@ -156,3 +150,4 @@ | ||
Here is a list of available commands. | ||
The commands flagged with [*] require the private key of the authentication contract owner to be available to the script, for example by exporting it with `export PK=<private key>`. | ||
The commands flagged with [**] require exporting the private key of the authentication contract owner, while those flagged with [*] require the address of either the owner or the manager. | ||
The private key can be exported with `export PK=<private key>`. | ||
@@ -162,2 +157,4 @@ 1. `add $ADDRESS` [*]. Adds the address to the list of registered solvers. | ||
3. `check $ADDRESS`. Checks if the given address is in the list of registered solvers. | ||
3. `list`. Lists all registered solvers. | ||
3. `setManager $ADDRESS` [**]. Sets the manager of the authenticator to the input address. | ||
@@ -171,2 +168,12 @@ For example, adding the address `0x0000000000000000000000000000000000000042` to the solver list: | ||
### Transfer Ownership | ||
There is a dedicated script to change the owner of the authenticator proxy. | ||
Usage and parameters can be seen by running: | ||
```sh | ||
yarn hardhat transfer-ownership --help | ||
``` | ||
### Fee Withdrawals | ||
@@ -203,1 +210,13 @@ | ||
Note that you will be expected to have your `INFURA_KEY` exported to your environment variables. | ||
## Releases | ||
The content of this repo is published on NPM as [`@cowprotocol/contracts`](https://www.npmjs.com/package/@cowprotocol/contracts). | ||
Maintainers this repository can manually trigger a new release. The steps are as follows: | ||
1. Update the package version number in `./package.json` on branch `main`. | ||
2. On GitHub, visit the "Actions" tab, "Publish package to NPM", "Run workflow" with `main` as the target branch. | ||
Once the workflow has been executed successfully, a new NPM package version should be available as well as a new git tag named after the released version. |
@@ -27,6 +27,6 @@ import "@nomiclabs/hardhat-ethers"; | ||
import { | ||
APP_DATA, | ||
assertNotBuyingNativeAsset, | ||
computeValidTo, | ||
getQuote, | ||
computeValidTo, | ||
APP_DATA, | ||
MAX_ORDER_VALIDITY_SECONDS, | ||
@@ -41,3 +41,2 @@ Quote, | ||
import { createGasEstimator, IGasEstimator } from "./ts/gas"; | ||
import { fastTokenDetails } from "./ts/oneinch_tokens"; | ||
import { | ||
@@ -52,2 +51,3 @@ DisappearingLogFunctions, | ||
import { | ||
formatGasCost, | ||
formatTokenValue, | ||
@@ -59,3 +59,2 @@ formatUsdValue, | ||
usdValueOfEth, | ||
formatGasCost, | ||
} from "./ts/value"; | ||
@@ -303,3 +302,3 @@ import { BalanceOutput, getAmounts } from "./withdraw"; | ||
async ({ consoleLog }: DisappearingLogFunctions) => { | ||
const sellToken = await fastTokenDetails(tokenAddress, hre); | ||
const sellToken = await erc20Token(tokenAddress, hre); | ||
if (sellToken === null) { | ||
@@ -530,2 +529,3 @@ throw new Error( | ||
notifySlackChannel?: string; | ||
maxOrders: number; | ||
} | ||
@@ -554,2 +554,3 @@ | ||
domainSeparator, | ||
maxOrders, | ||
}: SelfSellInput): Promise<{ | ||
@@ -678,2 +679,14 @@ orders: OrderDetails[]; | ||
} | ||
if (orders.length > maxOrders) { | ||
console.log(`Truncating total of ${orders.length} order to ${maxOrders}`); | ||
// Remove the least profitable orders | ||
orders = orders | ||
.sort((o1, o2) => { | ||
const first_proceeds = o1.sellAmountUsd.sub(o1.feeUsd); | ||
const second_proceeds = o2.sellAmountUsd.sub(o2.feeUsd); | ||
// We want to sort in descending order | ||
return first_proceeds.lt(second_proceeds) ? 1 : -1; | ||
}) | ||
.slice(0, maxOrders); | ||
} | ||
displayOrders(orders, usdReference, toToken); | ||
@@ -896,6 +909,3 @@ | ||
) | ||
.addOptionalParam( | ||
"toToken", | ||
"All input tokens will be dumped to this token. If not specified, it defaults to the network's native token (e.g., ETH)", | ||
) | ||
.addParam("toToken", "All input tokens will be dumped to this token.") | ||
.addFlag( | ||
@@ -909,2 +919,12 @@ "safe", | ||
) | ||
.addOptionalParam( | ||
"maxOrders", | ||
"Limit the amount of orders per settlement to this value.", | ||
50, | ||
types.int, | ||
) | ||
.addOptionalVariadicPositionalParam( | ||
"tokens", | ||
"The list of tokens to sell. If unspecified, the script will generate this list automatically.", | ||
) | ||
.setAction( | ||
@@ -928,2 +948,4 @@ async ( | ||
doNotPrompt, | ||
maxOrders, | ||
tokens, | ||
}, | ||
@@ -961,10 +983,13 @@ hre: HardhatRuntimeEnvironment, | ||
if (tokens == undefined || tokens.length === 0) { | ||
tokens = await getTokensWithBalanceAbove({ | ||
chainId, | ||
settlementContract: settlementDeployment.address, | ||
minValueUsd: parseInt(minValue), | ||
}); | ||
} | ||
// Exclude the toToken if needed, as we can not sell it for itself (buyToken is not allowed to equal sellToken) | ||
const tokens = ( | ||
await getTokensWithBalanceAbove( | ||
minValue, | ||
settlementDeployment.address, | ||
) | ||
).filter( | ||
(token) => utils.getAddress(token) != utils.getAddress(toToken), | ||
tokens = tokens.filter( | ||
(token: string) => | ||
utils.getAddress(token) != utils.getAddress(toToken), | ||
); | ||
@@ -996,2 +1021,3 @@ | ||
doNotPrompt, | ||
maxOrders, | ||
}); | ||
@@ -998,0 +1024,0 @@ }, |
@@ -6,3 +6,9 @@ import { Contract } from "ethers"; | ||
const supportedNetworks = ["rinkeby", "goerli", "xdai", "mainnet"] as const; | ||
const supportedNetworks = [ | ||
"rinkeby", | ||
"goerli", | ||
"xdai", | ||
"mainnet", | ||
"sepolia", | ||
] as const; | ||
export type SupportedNetwork = (typeof supportedNetworks)[number]; | ||
@@ -9,0 +15,0 @@ export function isSupportedNetwork( |
@@ -33,2 +33,3 @@ import WethNetworks from "canonical-weth/networks.json"; | ||
goerli: "ETH", | ||
sepolia: "ETH", | ||
xdai: "xDAI", | ||
@@ -40,2 +41,3 @@ }; | ||
rinkeby: WethNetworks.WETH9[4].address, | ||
sepolia: "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14", | ||
goerli: "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6", | ||
@@ -42,0 +44,0 @@ xdai: "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d", |
@@ -34,2 +34,7 @@ import { BigNumber, utils } from "ethers"; | ||
}, | ||
sepolia: { | ||
symbol: "DAI", | ||
decimals: 18, | ||
address: "0xB4F1737Af37711e9A5890D9510c9bB60e170CB0D", | ||
}, | ||
xdai: { | ||
@@ -36,0 +41,0 @@ // todo: replace with XDAI when native token price queries will be supported |
@@ -23,3 +23,2 @@ import "@nomiclabs/hardhat-ethers"; | ||
import { createGasEstimator, IGasEstimator } from "./ts/gas"; | ||
import { fastTokenDetails } from "./ts/oneinch_tokens"; | ||
import { | ||
@@ -31,3 +30,3 @@ DisappearingLogFunctions, | ||
import { Align, displayTable } from "./ts/table"; | ||
import { Erc20Token } from "./ts/tokens"; | ||
import { erc20Token, Erc20Token } from "./ts/tokens"; | ||
import { | ||
@@ -251,3 +250,3 @@ formatTokenValue, | ||
async ({ consoleLog }: DisappearingLogFunctions) => { | ||
const token = await fastTokenDetails(tokenAddress, hre); | ||
const token = await erc20Token(tokenAddress, hre); | ||
if (token === null) { | ||
@@ -254,0 +253,0 @@ throw new Error( |
import SafeApiKit from "@safe-global/api-kit"; | ||
import Safe, { EthersAdapter } from "@safe-global/protocol-kit"; | ||
import { SafeTransactionDataPartial } from "@safe-global/safe-core-sdk-types"; | ||
import { HardhatRuntimeEnvironment } from "hardhat/types"; | ||
@@ -12,3 +13,3 @@ | ||
function serviceUrlForNetwork(network: string): string { | ||
if (["goerli", "mainnet", "gnosis-chain"].includes(network)) { | ||
if (["goerli", "mainnet", "gnosis-chain", "sepolia"].includes(network)) { | ||
return `https://safe-transaction-${network}.safe.global`; | ||
@@ -22,2 +23,15 @@ } else if (network === "xdai") { | ||
interface SafesAddressNoncesOutput { | ||
recommendedNonce: number; | ||
} | ||
// Once `@safe-global/api-kit` has been migrated from v1 to v2, this can be replaced with `getnextnonce`. | ||
// <https://docs.safe.global/sdk-api-kit/reference#getnextnonce> | ||
async function recommendedNonce(chainId: number, safeAddress: string) { | ||
// <https://safe-client.safe.global/index.html#/safes/SafesController_getNonces> | ||
const url = `https://safe-client.safe.global/v1/chains/${chainId.toString()}/safes/${safeAddress}/nonces`; | ||
const response = await fetch(url); | ||
const output: SafesAddressNoncesOutput = await response.json(); | ||
return output.recommendedNonce; | ||
} | ||
// Creates and proposes a transaction to the Safe Multisig, which can then be confirmed by other signers in the Web UI. Returns the link to the transaction in the Web UI. | ||
@@ -29,2 +43,3 @@ export async function proposeTransaction( | ||
): Promise<string> { | ||
const { chainId } = await ethers.provider.getNetwork(); | ||
const [proposer] = await ethers.getSigners(); | ||
@@ -35,7 +50,15 @@ const ethAdapter = new EthersAdapter({ | ||
}); | ||
let nonce; | ||
try { | ||
nonce = await recommendedNonce(chainId, authoringSafe); | ||
} catch { | ||
console.log("Unable to determine recommended nonce, using current one"); | ||
nonce = undefined; | ||
} | ||
const safeTransactionData = { | ||
const safeTransactionData: SafeTransactionDataPartial = { | ||
to, | ||
data, | ||
value: "0", | ||
nonce, | ||
}; | ||
@@ -42,0 +65,0 @@ |
import axios from "axios"; | ||
interface AddressInfoResponse { | ||
export interface GetTokensInput { | ||
minValueUsd: number; | ||
settlementContract: string; | ||
chainId: number; | ||
} | ||
export async function getTokensWithBalanceAbove({ | ||
minValueUsd, | ||
settlementContract, | ||
chainId, | ||
}: GetTokensInput): Promise<string[]> { | ||
switch (chainId) { | ||
case 1: | ||
return await getMainnetTokensWithBalanceAbove( | ||
minValueUsd, | ||
settlementContract, | ||
); | ||
case 100: | ||
return await getGnosisChainTokensWithBalanceAbove( | ||
minValueUsd, | ||
settlementContract, | ||
); | ||
default: | ||
throw new Error( | ||
`Automatic token list generation is not supported on chain with id ${chainId}`, | ||
); | ||
} | ||
} | ||
interface EthplorerAddressInfoResponse { | ||
tokens: { | ||
@@ -16,4 +45,4 @@ tokenInfo: { | ||
export async function getTokensWithBalanceAbove( | ||
minValueUsd: string, | ||
export async function getMainnetTokensWithBalanceAbove( | ||
minValueUsd: number, | ||
settlementContract: string, | ||
@@ -28,3 +57,3 @@ ): Promise<string[]> { | ||
const result = []; | ||
const data = response.data as AddressInfoResponse; | ||
const data = response.data as EthplorerAddressInfoResponse; | ||
for (const token of data.tokens) { | ||
@@ -34,3 +63,3 @@ const tokenUsdValue = | ||
(token.balance / Math.pow(10, token.tokenInfo.decimals)); | ||
if (tokenUsdValue > parseInt(minValueUsd)) { | ||
if (tokenUsdValue > minValueUsd) { | ||
result.push(token.tokenInfo.address); | ||
@@ -41,1 +70,34 @@ } | ||
} | ||
type BlockscoutAddressInfoResponse = BlockscoutSingleTokenInfo[]; | ||
interface BlockscoutSingleTokenInfo { | ||
token: { | ||
address: string; | ||
exchange_rate: string; | ||
decimals: string; | ||
}; | ||
value: string; | ||
} | ||
export async function getGnosisChainTokensWithBalanceAbove( | ||
minValueUsd: number, | ||
settlementContract: string, | ||
): Promise<string[]> { | ||
const response = await axios.get( | ||
`https://gnosis.blockscout.com/api/v2/addresses/${settlementContract}/token-balances`, | ||
); | ||
if (response.status !== 200) { | ||
throw new Error(`Error getting tokens from ETHplorer ${response}`); | ||
} | ||
const result = []; | ||
const data = response.data as BlockscoutAddressInfoResponse; | ||
for (const { value, token } of data) { | ||
const tokenUsdValue = | ||
parseFloat(token.exchange_rate) * | ||
(parseInt(value) / Math.pow(10, parseInt(token.decimals))); | ||
if (tokenUsdValue > minValueUsd) { | ||
result.push(token.address); | ||
} | ||
} | ||
return result; | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2872704
229
33715
218