101 lines
2.7 KiB
TypeScript
101 lines
2.7 KiB
TypeScript
import { Contract } from 'ethers'
|
|
import { Web3Provider } from 'ethers/providers'
|
|
import {
|
|
BigNumber,
|
|
bigNumberify,
|
|
getAddress,
|
|
keccak256,
|
|
defaultAbiCoder,
|
|
toUtf8Bytes,
|
|
solidityPack
|
|
} from 'ethers/utils'
|
|
|
|
const PERMIT_TYPEHASH = keccak256(
|
|
toUtf8Bytes('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)')
|
|
)
|
|
|
|
export function expandTo18Decimals(n: number): BigNumber {
|
|
return bigNumberify(n).mul(bigNumberify(10).pow(18))
|
|
}
|
|
|
|
function getDomainSeparator(name: string, tokenAddress: string) {
|
|
return keccak256(
|
|
defaultAbiCoder.encode(
|
|
['bytes32', 'bytes32', 'bytes32', 'uint256', 'address'],
|
|
[
|
|
keccak256(toUtf8Bytes('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)')),
|
|
keccak256(toUtf8Bytes(name)),
|
|
keccak256(toUtf8Bytes('1')),
|
|
1,
|
|
tokenAddress
|
|
]
|
|
)
|
|
)
|
|
}
|
|
|
|
export function getCreate2Address(
|
|
factoryAddress: string,
|
|
token0Address: string,
|
|
token1Address: string,
|
|
bytecode: string
|
|
): string {
|
|
const create2Inputs = [
|
|
'0xff',
|
|
factoryAddress,
|
|
keccak256(solidityPack(['address', 'address'], [token0Address, token1Address])),
|
|
keccak256(bytecode)
|
|
]
|
|
const sanitizedInputs = `0x${create2Inputs.map(i => i.slice(2)).join('')}`
|
|
return getAddress(`0x${keccak256(sanitizedInputs).slice(-40)}`)
|
|
}
|
|
|
|
export async function getApprovalDigest(
|
|
token: Contract,
|
|
approve: {
|
|
owner: string
|
|
spender: string
|
|
value: BigNumber
|
|
},
|
|
nonce: BigNumber,
|
|
expiration: BigNumber
|
|
): Promise<string> {
|
|
const name = await token.name()
|
|
const DOMAIN_SEPARATOR = getDomainSeparator(name, token.address)
|
|
return keccak256(
|
|
solidityPack(
|
|
['bytes1', 'bytes1', 'bytes32', 'bytes32'],
|
|
[
|
|
'0x19',
|
|
'0x01',
|
|
DOMAIN_SEPARATOR,
|
|
keccak256(
|
|
defaultAbiCoder.encode(
|
|
['bytes32', 'address', 'address', 'uint256', 'uint256', 'uint256'],
|
|
[PERMIT_TYPEHASH, approve.owner, approve.spender, approve.value, nonce, expiration]
|
|
)
|
|
)
|
|
]
|
|
)
|
|
)
|
|
}
|
|
|
|
async function mineBlock(provider: Web3Provider, timestamp?: number): Promise<void> {
|
|
await new Promise((resolve, reject) => {
|
|
;(provider._web3Provider.sendAsync as any)(
|
|
{ jsonrpc: '2.0', method: 'evm_mine', params: timestamp ? [timestamp] : [] },
|
|
(error: any, result: any): void => {
|
|
if (error) {
|
|
reject(error)
|
|
} else {
|
|
resolve(result)
|
|
}
|
|
}
|
|
)
|
|
})
|
|
}
|
|
|
|
export async function mineBlocks(provider: Web3Provider, numberOfBlocks: number, timestamp?: number): Promise<void> {
|
|
await Promise.all([...Array(numberOfBlocks - 1)].map(() => mineBlock(provider)))
|
|
await mineBlock(provider, timestamp)
|
|
}
|