According to ethers.js documentation:
contract.attach( addressOrName ) ⇒ Contract
Returns a new instance of the Contract attached to a new address. This is useful if there are multiple similar or identical copies of a Contract on the network and you wish to interact with each of them.
But I don't really understand the use of it. Can someone explain it in a more easy-to-follow manner? Here's an example of .attach in use found in "Compromise" level of CTF challenge DamnVulnerableDefi.
this.oracle = await TrustfulOracleFactory.attach(
await (
await TrustfulOracleInitializerFactory.deploy(
sources,
['DVNFT', 'DVNFT', 'DVNFT'],
[INITIAL_NFT_PRICE, INITIAL_NFT_PRICE, INITIAL_NFT_PRICE]
)
).oracle()
What is this code exactly doing and why is the attach method needed?
Can someone explain it in a more easy-to-follow manner?
Attach creates a new contract instance from an already deployed contract, and from an existing instance ( reuses the same ABI and Signer ).
This is useful for example, if you have the same contract deployed on different blockchains, so you won't need to recreate the instance when the user changes to the network.
Or if you have a contract factory that deploys the same contract several times on the same network, and instead of creating an instance of each one of them, you can create them all from just one instance, so you don't have to go through the hassle of specifying the ABI file and the Signer.
What is this code exactly doing and why is the attach method needed?
I am not an expert, nor I'm 100% sure what this code does since I don't have that contracts code. Yet I can speculate the following.
// Returns value of calling the oracle() method of the new contract instance.
this.oracle = await TrustfulOracleFactory.attach(
// waits for the deployment to finish ( kinda redundat here ).
await (
// waits until the contract is deployed, this returns an address.
// the values in .deploy(...) are values passed to the constructor of the contract.
await TrustfulOracleInitializerFactory.deploy(
sources,
['DVNFT', 'DVNFT', 'DVNFT'],
[INITIAL_NFT_PRICE, INITIAL_NFT_PRICE, INITIAL_NFT_PRICE]
// On the new returned instance, call method Oracle.
)).oracle()
//--------- Step by Step code ---------------
// Deploys contract, returns address.
let newContractAddress = await TrustfulOracleInitializerFactory.deploy(
sources,
['DVNFT', 'DVNFT', 'DVNFT'],
[INITIAL_NFT_PRICE, INITIAL_NFT_PRICE, INITIAL_NFT_PRICE]
);
// Get instance from address and previusly created instance ( reuse of the same ABI as TrustfulOracleFactory )
let oracleInstance = await TrustfulOracleFactory.attach(newContractAddress);
// Calls oracle method.
this.oracle = await oracleInstance.oracle();