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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* Imports: External */
import { Contract } from 'ethers'
import { Provider } from '@ethersproject/abstract-provider'
import { Signer } from '@ethersproject/abstract-signer'
export const registerAddress = async ({
hre,
name,
address,
}): Promise<void> => {
// TODO: Cache these 2 across calls?
const { deployer } = await hre.getNamedAccounts()
const Lib_AddressManager = await getDeployedContract(
hre,
'Lib_AddressManager',
{
signerOrProvider: deployer,
}
)
const currentAddress = await Lib_AddressManager.getAddress(name)
if (address === currentAddress) {
console.log(
`✓ Not registering address for ${name} because it's already been correctly registered`
)
return
}
console.log(`Registering address for ${name} to ${address}...`)
const tx = await Lib_AddressManager.setAddress(name, address)
await tx.wait()
const remoteAddress = await Lib_AddressManager.getAddress(name)
if (remoteAddress !== address) {
throw new Error(
`\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` +
`Call to Lib_AddressManager.setAddress(${name}) was unsuccessful.\n` +
`Attempted to set address to: ${address}\n` +
`Actual address was set to: ${remoteAddress}\n` +
`This could indicate a compromised deployment.`
)
}
console.log(`✓ Registered address for ${name}`)
}
export const deployAndRegister = async ({
hre,
name,
args,
contract,
}: {
hre: any
name: string
args: any[]
contract?: string
}) => {
const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts()
const result = await deploy(name, {
contract,
from: deployer,
args,
log: true,
})
await hre.ethers.provider.waitForTransaction(result.transactionHash)
if (result.newlyDeployed) {
await registerAddress({
hre,
name,
address: result.address,
})
}
}
export const getDeployedContract = async (
hre: any,
name: string,
options: {
iface?: string
signerOrProvider?: Signer | Provider | string
} = {}
): Promise<Contract> => {
const deployed = await hre.deployments.get(name)
await hre.ethers.provider.waitForTransaction(deployed.receipt.transactionHash)
// Get the correct interface.
let iface = new hre.ethers.utils.Interface(deployed.abi)
if (options.iface) {
const factory = await hre.ethers.getContractFactory(options.iface)
iface = factory.interface
}
let signerOrProvider: Signer | Provider = hre.ethers.provider
if (options.signerOrProvider) {
if (typeof options.signerOrProvider === 'string') {
signerOrProvider = hre.ethers.provider.getSigner(options.signerOrProvider)
} else {
signerOrProvider = options.signerOrProvider
}
}
// Temporarily override Object.defineProperty to bypass ether's object protection.
const def = Object.defineProperty
Object.defineProperty = (obj, propName, prop) => {
prop.writable = true
return def(obj, propName, prop)
}
const contract = new Contract(deployed.address, iface, signerOrProvider)
// Now reset Object.defineProperty
Object.defineProperty = def
// Override each function call to also `.wait()` so as to simplify the deploy scripts' syntax.
for (const fnName of Object.keys(contract.functions)) {
const fn = contract[fnName].bind(contract)
;(contract as any)[fnName] = async (...args: any) => {
const result = await fn(...args)
if (typeof result === 'object' && typeof result.wait === 'function') {
await result.wait()
}
return result
}
}
return contract
}