ABI's from //contract/out URLs; arbsep; placement fee considers upcoming fee changes; vault detection bugfixes; order placement bugfixes; BETA
This commit is contained in:
@@ -1,109 +0,0 @@
|
||||
|
||||
export const factoryAbi = [
|
||||
'function deployVault() returns (address payable vault)',
|
||||
'function deployVault(uint8 num) returns (address payable vault)',
|
||||
'function deployVault(address owner) returns (address payable vault)',
|
||||
'function deployVault(address owner, uint8 num) returns (address payable vault)',
|
||||
'function logic() view returns (address)',
|
||||
'function upgrader() view returns (address)',
|
||||
'function proposedLogicActivationTimestamp() view returns (uint32)',
|
||||
'function proposedLogic() view returns (address)',
|
||||
'function upgradeLogic(address newLogic)',
|
||||
]
|
||||
|
||||
export const queryHelperAbi = [
|
||||
'function getRoutes(address tokenA,address tokenB) view returns((uint8,uint24,address)[])',
|
||||
]
|
||||
|
||||
export const uniswapV3PoolAbi = [
|
||||
// {
|
||||
// // the current price
|
||||
// uint160 sqrtPriceX96;
|
||||
// // the current tick
|
||||
// int24 tick;
|
||||
// // the most-recently updated index of the observations array
|
||||
// uint16 observationIndex;
|
||||
// // the current maximum number of observations that are being stored
|
||||
// uint16 observationCardinality;
|
||||
// // the next maximum number of observations to store, triggered in observations.write
|
||||
// uint16 observationCardinalityNext;
|
||||
// // the current protocol fee as a percentage of the swap fee taken on withdrawal
|
||||
// // represented as an integer denominator (1/x)%
|
||||
// uint8 feeProtocol;
|
||||
// // whether the pool is locked
|
||||
// bool unlocked;
|
||||
// }
|
||||
'function slot0() view returns(uint160,int24,uint16,uint16,uint16,uint8,bool)',
|
||||
'function token0() view returns(address)',
|
||||
'function token1() view returns(address)',
|
||||
]
|
||||
|
||||
export const erc20Abi = [
|
||||
'function name() view returns (string)',
|
||||
'function symbol() view returns (string)',
|
||||
'function decimals() view returns (uint8)',
|
||||
'function totalSupply() view returns (uint256)',
|
||||
'function balanceOf(address) view returns (uint256)',
|
||||
'function transfer(address,uint256) returns (bool)',
|
||||
'function transferFrom(address,address,uint256) returns (bool)',
|
||||
'function approve(address,uint256) returns (bool success)',
|
||||
'function allowance(address,address) view returns (uint256)',
|
||||
'event Transfer(address indexed,address indexed,uint256)',
|
||||
'event Approval(address indexed,address indexed,uint256)',
|
||||
]
|
||||
|
||||
export const mockErc20Abi = [...erc20Abi,
|
||||
'function mint(address,uint256)',
|
||||
]
|
||||
|
||||
const Route = '(uint8 exchange, uint24 fee)'
|
||||
const Tranche = `(
|
||||
uint16 fraction,
|
||||
bool startTimeIsRelative,
|
||||
bool endTimeIsRelative,
|
||||
bool minIsBarrier,
|
||||
bool maxIsBarrier,
|
||||
bool marketOrder,
|
||||
bool minIsRatio,
|
||||
bool maxIsRatio,
|
||||
bool _reserved7,
|
||||
uint16 rateLimitFraction,
|
||||
uint24 rateLimitPeriod,
|
||||
uint32 startTime,
|
||||
uint32 endTime,
|
||||
uint32 minIntercept,
|
||||
uint32 minSlope,
|
||||
uint32 maxIntercept,
|
||||
uint32 maxSlope
|
||||
)`
|
||||
|
||||
const SwapOrder = `(
|
||||
address tokenIn,
|
||||
address tokenOut,
|
||||
${Route} route,
|
||||
uint256 amount,
|
||||
uint256 minFillAmount,
|
||||
bool amountIsInput,
|
||||
bool outputDirectlyToOwner,
|
||||
uint64 conditionalOrder,
|
||||
${Tranche}[] tranches
|
||||
)`
|
||||
|
||||
export const vaultAbi = [
|
||||
'function version() pure returns (uint8)',
|
||||
'function logic() view returns (address)',
|
||||
'function upgrade(address)',
|
||||
'function feeManager() view returns (address)',
|
||||
'function withdraw(uint256 amount)',
|
||||
'function withdrawTo(address payable recipient, uint256 amount)',
|
||||
'function withdraw(address token, uint256 amount)',
|
||||
'function withdrawTo(address token, address recipient, uint256 amount)',
|
||||
'function numSwapOrders() view returns (uint64 num)',
|
||||
`function placementFee(${SwapOrder} order) view returns (uint256 orderFee, uint256 gasFee)`,
|
||||
`function placeDexorder(${SwapOrder}) payable`,
|
||||
`function placeDexorders(${SwapOrder}[], uint8 ocoMode) payable`,
|
||||
'function cancelDexorder(uint64 orderIndex)',
|
||||
'function cancelAllDexorders()',
|
||||
// `function swapOrderStatus(uint64 orderIndex) view returns (${SwapOrderStatus} memory status)`,
|
||||
'function orderCanceled(uint64 orderIndex) view returns (bool)',
|
||||
]
|
||||
@@ -1,5 +1,7 @@
|
||||
import {ethers} from "ethers";
|
||||
import {queryHelperAbi} from "@/blockchain/abi.js";
|
||||
import {AbiURLCache} from "../common.js";
|
||||
|
||||
export const abiCache = new AbiURLCache('/contract/out/')
|
||||
|
||||
|
||||
export function vaultAddress( factory, vaultInitCodeHash, owner, num=0) {
|
||||
@@ -20,6 +22,23 @@ export function contractOrNull(addr,abi,provider) {
|
||||
}
|
||||
|
||||
export async function queryHelperContract(helper, provider) {
|
||||
return contractOrNull(helper, queryHelperAbi, provider)
|
||||
return newContract(helper, 'QueryHelper', provider)
|
||||
}
|
||||
|
||||
|
||||
// do not supply extensions with name or file: e.g.
|
||||
// use newContract(addr, 'IVaultLogic', provider, 'IVault') to get the ABI from IVault.sol/IVaultLogic.json
|
||||
export async function newContract(addr, name, provider) {
|
||||
const abi = await abiCache.get(name)
|
||||
return new ethers.Contract(addr, abi, provider)
|
||||
}
|
||||
|
||||
|
||||
export async function erc20Contract(addr, provider) {
|
||||
return newContract(addr, 'IERC20Metadata', provider)
|
||||
}
|
||||
|
||||
|
||||
export async function vaultContract(addr, provider) {
|
||||
return await newContract(addr, 'IVault', provider)
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ export function newTranche({
|
||||
endTime = DISTANT_FUTURE,
|
||||
minIsBarrier = false,
|
||||
minIsRatio = false,
|
||||
minIntercept = 0,
|
||||
slippage = 0, // may also set minIntercept instead
|
||||
minIntercept = 0,
|
||||
minSlope = 0,
|
||||
maxIsBarrier = false,
|
||||
maxIsRatio = false,
|
||||
@@ -200,3 +200,14 @@ export function parseTranche(tranche) {
|
||||
startTime, endTime, minIntercept, minSlope, maxIntercept, maxSlope,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function parseFeeSchedule(sched) {
|
||||
const [orderFee, orderExp, gasFee, gasExp, fillFeeHalfBps] = sched
|
||||
return {
|
||||
orderFee: orderFee << orderExp, // orderFee is in native (ETH) currency
|
||||
gasFee: gasFee << gasExp, // gasFee is in native (ETH) currency
|
||||
fillFee: fillFeeHalfBps/1_000_000 // fillFee is a multiplier on the filled volume. 0.0001 = 0.1% of the output token taken as a fee
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,9 @@ import {socket} from "@/socket.js";
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {Exchange} from "@/blockchain/orderlib.js";
|
||||
import {uniswapV3PoolAddress} from "@/blockchain/uniswap.js";
|
||||
import {ethers, FixedNumber} from "ethers";
|
||||
import {uniswapV3PoolAbi} from "@/blockchain/abi.js";
|
||||
import {subOHLCs} from "@/blockchain/ohlcs.js";
|
||||
import {FixedNumber} from "ethers";
|
||||
import {provider} from "@/blockchain/wallet.js";
|
||||
import {newContract} from "@/blockchain/contract.js";
|
||||
|
||||
const subscriptionCounts = {} // key is route and value is a subscription counter
|
||||
export const WIDE_PRICE_FORMAT = {decimals:38, width:512, signed:false}; // 38 decimals is 127 bits
|
||||
@@ -84,7 +83,7 @@ async function getPriceForRoute(route) {
|
||||
console.error('provider was null during getPriceForRoute')
|
||||
return null
|
||||
}
|
||||
const pool = new ethers.Contract(addr, uniswapV3PoolAbi, provider)
|
||||
const pool = newContract(addr, 'IUniswapV3Pool', provider)
|
||||
const got = await pool.slot0()
|
||||
const [sqrtPrice,,,,,,] = got
|
||||
const spn = BigInt(sqrtPrice)
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import {socket} from "@/socket.js";
|
||||
import {useStore} from "@/store/store.js";
|
||||
import {erc20Abi} from "@/blockchain/abi.js";
|
||||
import {ethers} from "ethers";
|
||||
import {metadataMap} from "@/version.js";
|
||||
import {provider} from "@/blockchain/wallet.js";
|
||||
import {newContract} from "@/blockchain/contract.js";
|
||||
|
||||
|
||||
// synchronous version may return null but will trigger a lookup
|
||||
@@ -64,7 +63,7 @@ export async function addExtraToken(chainId, addr) {
|
||||
resolve(null)
|
||||
}
|
||||
else {
|
||||
const token = new ethers.Contract(addr, erc20Abi, provider)
|
||||
const token = newContract(addr, 'IERC20Metadata', provider)
|
||||
Promise.all( [token.name(), token.symbol(), token.decimals()] ).then((name,symbol,decimals)=>{
|
||||
info = {
|
||||
a: addr,
|
||||
|
||||
@@ -2,13 +2,16 @@ import {ethers} from "ethers";
|
||||
|
||||
const UNISWAPV3_POOL_INIT_CODE_HASH = '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54'
|
||||
const uniswapV3Addresses = {
|
||||
1337: {
|
||||
31337: { // Mockchain
|
||||
factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
|
||||
},
|
||||
42161: {
|
||||
1337: { // Dexorder Alpha
|
||||
factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
|
||||
},
|
||||
31337: {
|
||||
421614: { // Arbitrum Sepolia
|
||||
factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
|
||||
},
|
||||
42161: { // Arbitrum
|
||||
factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import {BrowserProvider, ethers} from "ethers";
|
||||
import {useStore} from "@/store/store";
|
||||
import {socket} from "@/socket.js";
|
||||
import {contractOrNull, vaultAddress} from "@/blockchain/contract.js";
|
||||
import {SingletonCoroutine, uuid} from "@/misc.js";
|
||||
import {factoryAbi, vaultAbi} from "@/blockchain/abi.js";
|
||||
import {newContract, vaultAddress, vaultContract} from "@/blockchain/contract.js";
|
||||
import {SingletonCoroutine, timestamp, uuid} from "@/misc.js";
|
||||
import {defineStore} from "pinia";
|
||||
import {ref} from "vue";
|
||||
import {metadataMap, version} from "@/version.js";
|
||||
@@ -217,7 +216,7 @@ async function _discoverVaults(owner) {
|
||||
console.log('No provider')
|
||||
return // do not change whatever was already found
|
||||
}
|
||||
const vault = new ethers.Contract(addr, vaultAbi, provider)
|
||||
const vault = await vaultContract(addr, provider)
|
||||
try {
|
||||
const version = Number(await vault.version())
|
||||
console.log(`found vault #${num} v${version} at ${addr}`)
|
||||
@@ -295,11 +294,24 @@ export const PendingOrderState = {
|
||||
Sent: -102, // tx is awaiting blockchain mining
|
||||
}
|
||||
|
||||
const placementFeeSelector = 'placementFee((address,address,(uint8,uint24),uint256,uint256,bool,bool,uint64,(uint16,bool,bool,bool,bool,bool,bool,bool,bool,uint16,uint24,uint32,uint32,uint32,uint32,uint32,uint32)[]),(uint8,uint8,uint8,uint8,uint8))'
|
||||
|
||||
export async function placementFee(vault, order) {
|
||||
const v = new ethers.Contract(vault, vaultAbi, provider)
|
||||
const [orderFee, gasFee] = await v.placementFee(order)
|
||||
console.log('computed fees', orderFee, gasFee)
|
||||
export async function placementFee(vault, order, window=300) {
|
||||
// If the fees are about to change within `window` seconds of now, we send the higher native amount of the two fees.
|
||||
// If the fees sent are too much, the vault will refund the sender.
|
||||
const v = await vaultContract(vault, provider)
|
||||
const feeManagerAddr = await v.feeManager()
|
||||
const feeManager = await newContract(feeManagerAddr, 'IFeeManager', provider)
|
||||
const [sched, changeTimestamp] = await Promise.all([feeManager.fees(), feeManager.proposedFeeActivationTime()])
|
||||
console.log('sched', order, sched)
|
||||
let [orderFee, gasFee] = await v[placementFeeSelector](order, [...sched])
|
||||
console.log('placementFee', orderFee, gasFee)
|
||||
if (Number(changeTimestamp) - timestamp() < window) {
|
||||
const nextSched = await feeManager.proposedFees()
|
||||
const [nextOrderFee, nextGasFee] = await v[placementFeeSelector](order, [...nextSched])
|
||||
if (nextOrderFee + nextGasFee > orderFee + gasFee)
|
||||
[orderFee, gasFee] = [nextOrderFee, nextGasFee]
|
||||
}
|
||||
return [orderFee, gasFee]
|
||||
}
|
||||
|
||||
@@ -324,7 +336,7 @@ export async function pendOrder(order, fee=null) {
|
||||
export async function cancelOrder(vault, orderIndex) {
|
||||
console.log('cancel order', vault, orderIndex)
|
||||
pendTransaction(async (signer)=> {
|
||||
const contract = contractOrNull(vault, vaultAbi, signer)
|
||||
const contract = await vaultContract(vault, signer)
|
||||
if( contract === null ) {
|
||||
console.error('vault contract was null while canceling order', vault, orderIndex)
|
||||
return null
|
||||
@@ -335,7 +347,7 @@ export async function cancelOrder(vault, orderIndex) {
|
||||
|
||||
export async function cancelAll(vault) {
|
||||
pendTransaction(async (signer)=> {
|
||||
const contract = contractOrNull(vault, vaultAbi, signer)
|
||||
const contract = await vaultContract(vault, signer)
|
||||
if( contract === null ) {
|
||||
console.error('vault contract was null while canceling order', vault)
|
||||
return null
|
||||
@@ -364,8 +376,12 @@ export function flushOrders(vault) {
|
||||
|
||||
function pendOrderAsTransaction(pend) {
|
||||
pendTransaction(async (signer)=> {
|
||||
const contract = contractOrNull(pend.vault, vaultAbi, signer)
|
||||
if( contract === null ) {
|
||||
// console.log('pendTransaction')
|
||||
let contract
|
||||
try {
|
||||
contract = await vaultContract(pend.vault, signer)
|
||||
}
|
||||
catch (e) {
|
||||
console.error('vault contract was null while sending order transaction', pend.vault)
|
||||
return null
|
||||
}
|
||||
@@ -491,15 +507,17 @@ export async function detectUpgrade() {
|
||||
}
|
||||
try {
|
||||
console.log('factory', info.factory)
|
||||
const factory = new ethers.Contract(info.factory, factoryAbi, provider)
|
||||
const vault = new ethers.Contract(s.vault, vaultAbi, provider)
|
||||
const [factory, vault] = await Promise.all([
|
||||
newContract(info.factory, 'IVaultFactory', provider),
|
||||
newContract(s.vault, 'IVault', provider),
|
||||
])
|
||||
const vaultLogic = await vault.logic()
|
||||
const latestLogic = await factory.logic()
|
||||
// const [vaultLogic, latestLogic] = await Promise.all( vault.logic(), factory.logic() )
|
||||
console.log('vaultLogic / latestLogic', vaultLogic, latestLogic)
|
||||
if ( vaultLogic !== latestLogic ) {
|
||||
s.upgrade = latestLogic
|
||||
const logic = new ethers.Contract(latestLogic, vaultAbi, provider)
|
||||
const logic = await newContract(latestLogic, 'IVault', provider)
|
||||
const version = await logic.version()
|
||||
console.log(`found vault version ${version}`)
|
||||
return version
|
||||
@@ -514,7 +532,7 @@ export async function detectUpgrade() {
|
||||
|
||||
function upgradeSender(vault, logic) {
|
||||
return async function (signer) {
|
||||
const v = new ethers.Contract(vault, vaultAbi, signer)
|
||||
const v = await vaultContract(vault, signer)
|
||||
v.upgrade(logic)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user