forked from alchemistcoin/alchemist
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.ts
113 lines (109 loc) · 2.99 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { TypedDataField } from '@ethersproject/abstract-signer'
import { Provider } from '@ethersproject/providers'
import { BigNumberish, Contract, ContractFactory, Signer, Wallet } from 'ethers'
import { splitSignature } from 'ethers/lib/utils'
export async function getTimestamp(provider: Provider) {
return (await provider.getBlock('latest')).timestamp
}
export async function deployContract(
name: string,
factory: ContractFactory,
signer: Signer,
args: Array<any> = [],
): Promise<Contract> {
const contract = await factory.connect(signer).deploy(...args)
console.log('Deploying', name)
console.log(' to', contract.address)
console.log(' in', contract.deployTransaction.hash)
return contract.deployed()
}
export const signPermission = async (
method: string,
vault: Contract,
owner: Wallet,
delegateAddress: string,
tokenAddress: string,
amount: BigNumberish,
vaultNonce: BigNumberish,
chainId?: BigNumberish,
) => {
// get chainId
chainId = chainId || (await vault.provider.getNetwork()).chainId
// craft permission
const domain = {
name: 'UniversalVault',
version: '1.0.0',
chainId: chainId,
verifyingContract: vault.address,
}
const types = {} as Record<string, TypedDataField[]>
types[method] = [
{ name: 'delegate', type: 'address' },
{ name: 'token', type: 'address' },
{ name: 'amount', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
]
const value = {
delegate: delegateAddress,
token: tokenAddress,
amount: amount,
nonce: vaultNonce,
}
// sign permission
// todo: add fallback if wallet does not support eip 712 rpc
const signedPermission = await owner._signTypedData(domain, types, value)
// return
return signedPermission
}
export const signPermitEIP2612 = async (
owner: Wallet,
token: Contract,
spenderAddress: string,
value: BigNumberish,
deadline: BigNumberish,
nonce?: BigNumberish,
) => {
// get nonce
nonce = nonce || (await token.nonces(owner.address))
// get chainId
const chainId = (await token.provider.getNetwork()).chainId
// get domain
const domain = {
name: 'Uniswap V2',
version: '1',
chainId: chainId,
verifyingContract: token.address,
}
// get types
const types = {} as Record<string, TypedDataField[]>
types['Permit'] = [
{ name: 'owner', type: 'address' },
{ name: 'spender', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' },
]
// get values
const values = {
owner: owner.address,
spender: spenderAddress,
value: value,
nonce: nonce,
deadline: deadline,
}
// sign permission
// todo: add fallback if wallet does not support eip 712 rpc
const signedPermission = await owner._signTypedData(domain, types, values)
// split signature
const sig = splitSignature(signedPermission)
// return
return [
values.owner,
values.spender,
values.value,
values.deadline,
sig.v,
sig.r,
sig.s,
]
}