github.com/ethereum-optimism/optimism@v1.7.2/packages/sdk/test/utils/contracts.spec.ts (about) 1 /* eslint-disable @typescript-eslint/no-empty-function */ 2 import { Signer } from 'ethers' 3 import { ethers } from 'hardhat' 4 5 import { expect } from '../setup' 6 import { 7 getOEContract, 8 getAllOEContracts, 9 CONTRACT_ADDRESSES, 10 DEFAULT_L2_CONTRACT_ADDRESSES, 11 L2ChainID, 12 } from '../../src' 13 14 describe('contract connection utils', () => { 15 let signers: Signer[] 16 before(async () => { 17 signers = (await ethers.getSigners()) as any 18 }) 19 20 describe('getOEContract', () => { 21 describe('when given a known chain ID', () => { 22 describe('when not given an address override', () => { 23 it('should use the address for the given contract name and chain ID', () => { 24 const addresses = CONTRACT_ADDRESSES[L2ChainID.OPTIMISM] 25 for (const [contractName, contractAddress] of [ 26 ...Object.entries(addresses.l1), 27 ...Object.entries(addresses.l2), 28 ]) { 29 const contract = getOEContract( 30 contractName as any, 31 L2ChainID.OPTIMISM 32 ) 33 expect(contract.address).to.equal(contractAddress) 34 } 35 }) 36 }) 37 38 describe('when given an address override', () => { 39 it('should use the custom address', () => { 40 const addresses = CONTRACT_ADDRESSES[L2ChainID.OPTIMISM] 41 for (const contractName of [ 42 ...Object.keys(addresses.l1), 43 ...Object.keys(addresses.l2), 44 ]) { 45 const address = '0x' + '11'.repeat(20) 46 const contract = getOEContract(contractName as any, 1, { 47 address, 48 }) 49 expect(contract.address).to.equal(address) 50 } 51 }) 52 }) 53 }) 54 55 describe('when given an unknown chain ID', () => { 56 describe('when not given an address override', () => { 57 it('should throw an error', () => { 58 expect(() => getOEContract('L1CrossDomainMessenger', 3)).to.throw() 59 }) 60 }) 61 62 describe('when given an address override', () => { 63 it('should use the custom address', () => { 64 const address = '0x' + '11'.repeat(20) 65 const contract = getOEContract('L1CrossDomainMessenger', 3, { 66 address, 67 }) 68 expect(contract.address).to.equal(address) 69 }) 70 }) 71 }) 72 73 describe('when connected to a valid address', () => { 74 it('should have the correct interface for the contract name', () => { 75 const contract = getOEContract( 76 'L1CrossDomainMessenger', 77 L2ChainID.OPTIMISM 78 ) 79 expect(contract.sendMessage).to.not.be.undefined 80 }) 81 82 describe('when not given a signer or provider', () => { 83 it('should not have a signer or provider', () => { 84 const contract = getOEContract( 85 'L1CrossDomainMessenger', 86 L2ChainID.OPTIMISM 87 ) 88 expect(contract.signer).to.be.null 89 expect(contract.provider).to.be.null 90 }) 91 }) 92 93 describe('when given a signer', () => { 94 it('should attach the given signer', () => { 95 const contract = getOEContract( 96 'L1CrossDomainMessenger', 97 L2ChainID.OPTIMISM, 98 { 99 signerOrProvider: signers[0], 100 } 101 ) 102 expect(contract.signer).to.deep.equal(signers[0]) 103 }) 104 }) 105 106 describe('when given a provider', () => { 107 it('should attach the given provider', () => { 108 const contract = getOEContract( 109 'L1CrossDomainMessenger', 110 L2ChainID.OPTIMISM, 111 { 112 signerOrProvider: ethers.provider as any, 113 } 114 ) 115 expect(contract.signer).to.be.null 116 expect(contract.provider).to.deep.equal(ethers.provider) 117 }) 118 }) 119 }) 120 }) 121 122 describe('getAllOEContracts', () => { 123 describe('when given a known chain ID', () => { 124 describe('when not given any address overrides', () => { 125 it('should return all contracts connected to the default addresses', () => { 126 const contracts = getAllOEContracts(L2ChainID.OPTIMISM) 127 const addresses = CONTRACT_ADDRESSES[L2ChainID.OPTIMISM] 128 for (const [contractName, contractAddress] of Object.entries( 129 addresses.l1 130 )) { 131 const contract = contracts.l1[contractName] 132 expect(contract.address).to.equal(contractAddress) 133 } 134 for (const [contractName, contractAddress] of Object.entries( 135 addresses.l2 136 )) { 137 const contract = contracts.l2[contractName] 138 expect(contract.address).to.equal(contractAddress) 139 } 140 }) 141 }) 142 143 describe('when given address overrides', () => { 144 it('should return contracts connected to the overridden addresses where given', () => { 145 const overrides = { 146 l1: { 147 L1CrossDomainMessenger: '0x' + '11'.repeat(20), 148 }, 149 l2: { 150 L2CrossDomainMessenger: '0x' + '22'.repeat(20), 151 }, 152 } 153 const contracts = getAllOEContracts(L2ChainID.OPTIMISM, { overrides }) 154 const addresses = CONTRACT_ADDRESSES[L2ChainID.OPTIMISM] 155 for (const [contractName, contractAddress] of Object.entries( 156 addresses.l1 157 )) { 158 const contract = contracts.l1[contractName] 159 if (overrides.l1[contractName]) { 160 expect(contract.address).to.equal(overrides.l1[contractName]) 161 } else { 162 expect(contract.address).to.equal(contractAddress) 163 } 164 } 165 for (const [contractName, contractAddress] of Object.entries( 166 addresses.l2 167 )) { 168 const contract = contracts.l2[contractName] 169 if (overrides.l2[contractName]) { 170 expect(contract.address).to.equal(overrides.l2[contractName]) 171 } else { 172 expect(contract.address).to.equal(contractAddress) 173 } 174 } 175 }) 176 }) 177 }) 178 179 describe('when given an unknown chain ID', () => { 180 describe('when given address overrides for all L1 contracts', () => { 181 describe('when given address overrides for L2 contracts', () => { 182 it('should return contracts connected to the overridden addresses where given', () => { 183 const l1Overrides = {} 184 for (const contractName of Object.keys( 185 CONTRACT_ADDRESSES[L2ChainID.OPTIMISM].l1 186 )) { 187 l1Overrides[contractName] = '0x' + '11'.repeat(20) 188 } 189 190 const contracts = getAllOEContracts(3, { 191 overrides: { 192 l1: l1Overrides as any, 193 l2: { 194 L2CrossDomainMessenger: '0x' + '22'.repeat(20), 195 }, 196 }, 197 }) 198 199 for (const [contractName, contract] of Object.entries( 200 contracts.l1 201 )) { 202 expect(contract.address).to.equal(l1Overrides[contractName]) 203 } 204 205 expect(contracts.l2.L2CrossDomainMessenger.address).to.equal( 206 '0x' + '22'.repeat(20) 207 ) 208 }) 209 }) 210 211 describe('when not given address overrides for L2 contracts', () => { 212 it('should return contracts connected to the default L2 addresses and custom L1 addresses', () => { 213 const l1Overrides = {} 214 for (const contractName of Object.keys( 215 CONTRACT_ADDRESSES[L2ChainID.OPTIMISM].l1 216 )) { 217 l1Overrides[contractName] = '0x' + '11'.repeat(20) 218 } 219 220 const contracts = getAllOEContracts(3, { 221 overrides: { 222 l1: l1Overrides as any, 223 }, 224 }) 225 226 for (const [contractName, contract] of Object.entries( 227 contracts.l1 228 )) { 229 expect(contract.address).to.equal(l1Overrides[contractName]) 230 } 231 232 for (const [contractName, contract] of Object.entries( 233 contracts.l2 234 )) { 235 expect(contract.address).to.equal( 236 DEFAULT_L2_CONTRACT_ADDRESSES[contractName] 237 ) 238 } 239 }) 240 }) 241 }) 242 243 describe('when given address overrides for some L1 contracts', () => { 244 it('should throw an error', () => { 245 expect(() => 246 getAllOEContracts(3, { 247 overrides: { 248 l1: { 249 L1CrossDomainMessenger: '0x' + '11'.repeat(20), 250 }, 251 }, 252 }) 253 ).to.throw() 254 }) 255 }) 256 257 describe('when given address overrides for no L1 contracts', () => { 258 it('should throw an error', () => { 259 expect(() => getAllOEContracts(3)).to.throw() 260 }) 261 }) 262 }) 263 264 describe('when not given a signer or provider', () => { 265 it('should not attach a signer or provider to any contracts', () => { 266 const contracts = getAllOEContracts(L2ChainID.OPTIMISM) 267 for (const contract of Object.values(contracts.l1)) { 268 expect(contract.signer).to.be.null 269 expect(contract.provider).to.be.null 270 } 271 for (const contract of Object.values(contracts.l2)) { 272 expect(contract.signer).to.be.null 273 expect(contract.provider).to.be.null 274 } 275 }) 276 }) 277 278 describe('when given an L1 signer', () => { 279 it('should attach the signer to the L1 contracts only', () => { 280 const contracts = getAllOEContracts(L2ChainID.OPTIMISM, { 281 l1SignerOrProvider: signers[0], 282 }) 283 for (const contract of Object.values(contracts.l1)) { 284 expect(contract.signer).to.deep.equal(signers[0]) 285 } 286 for (const contract of Object.values(contracts.l2)) { 287 expect(contract.signer).to.be.null 288 expect(contract.provider).to.be.null 289 } 290 }) 291 }) 292 293 describe('when given an L2 signer', () => { 294 it('should attach the signer to the L2 contracts only', () => { 295 const contracts = getAllOEContracts(L2ChainID.OPTIMISM, { 296 l2SignerOrProvider: signers[0], 297 }) 298 for (const contract of Object.values(contracts.l1)) { 299 expect(contract.signer).to.be.null 300 expect(contract.provider).to.be.null 301 } 302 for (const contract of Object.values(contracts.l2)) { 303 expect(contract.signer).to.deep.equal(signers[0]) 304 } 305 }) 306 }) 307 308 describe('when given an L1 signer and an L2 signer', () => { 309 it('should attach the signer to both sets of contracts', () => { 310 const contracts = getAllOEContracts(L2ChainID.OPTIMISM, { 311 l1SignerOrProvider: signers[0], 312 l2SignerOrProvider: signers[1], 313 }) 314 for (const contract of Object.values(contracts.l1)) { 315 expect(contract.signer).to.deep.equal(signers[0]) 316 } 317 for (const contract of Object.values(contracts.l2)) { 318 expect(contract.signer).to.deep.equal(signers[1]) 319 } 320 }) 321 }) 322 323 describe('when given an L1 provider', () => { 324 it('should attach the provider to the L1 contracts only', () => { 325 const contracts = getAllOEContracts(L2ChainID.OPTIMISM, { 326 l1SignerOrProvider: ethers.provider as any, 327 }) 328 for (const contract of Object.values(contracts.l1)) { 329 expect(contract.signer).to.be.null 330 expect(contract.provider).to.deep.equal(ethers.provider) 331 } 332 for (const contract of Object.values(contracts.l2)) { 333 expect(contract.signer).to.be.null 334 expect(contract.provider).to.be.null 335 } 336 }) 337 }) 338 339 describe('when given an L2 provider', () => { 340 it('should attach the provider to the L2 contracts only', () => { 341 const contracts = getAllOEContracts(L2ChainID.OPTIMISM, { 342 l2SignerOrProvider: ethers.provider as any, 343 }) 344 for (const contract of Object.values(contracts.l1)) { 345 expect(contract.signer).to.be.null 346 expect(contract.provider).to.be.null 347 } 348 for (const contract of Object.values(contracts.l2)) { 349 expect(contract.signer).to.be.null 350 expect(contract.provider).to.deep.equal(ethers.provider) 351 } 352 }) 353 }) 354 355 describe('when given an L1 provider and an L2 provider', () => { 356 it('should attach the provider to both sets of contracts', () => { 357 const contracts = getAllOEContracts(L2ChainID.OPTIMISM, { 358 l1SignerOrProvider: ethers.provider as any, 359 l2SignerOrProvider: ethers.provider as any, 360 }) 361 for (const contract of Object.values(contracts.l1)) { 362 expect(contract.signer).to.be.null 363 expect(contract.provider).to.deep.equal(ethers.provider) 364 } 365 for (const contract of Object.values(contracts.l2)) { 366 expect(contract.signer).to.be.null 367 expect(contract.provider).to.deep.equal(ethers.provider) 368 } 369 }) 370 }) 371 }) 372 })