{"id":852,"date":"2023-02-21T22:03:33","date_gmt":"2023-02-21T14:03:33","guid":{"rendered":"https:\/\/vinta.ws\/code\/?p=852"},"modified":"2026-02-18T01:20:34","modified_gmt":"2026-02-17T17:20:34","slug":"hardhat-deploy-upgradeable-contracts-with-linked-libraries","status":"publish","type":"post","link":"https:\/\/vinta.ws\/code\/hardhat-deploy-upgradeable-contracts-with-linked-libraries.html","title":{"rendered":"hardhat-deploy: Upgradeable Contracts with Linked Libraries"},"content":{"rendered":"<h2>Library<\/h2>\n<p>Assume <code>ContractA<\/code> imports <code>LibraryA<\/code>, when deploying <code>ContractA<\/code>, <code>LibraryA<\/code> is embedded into <code>ContractA<\/code> if <code>LibraryA<\/code> contains only <code>internal<\/code> functions.<\/p>\n<p>If <code>LibraryA<\/code> contains at least one <code>external<\/code> function, <code>LibraryA<\/code> must be deployed first, and then linked when deploying <code>ContractA<\/code>.<\/p>\n<p>ref:<br \/>\n<a href=\"https:\/\/solidity-by-example.org\/library\/\">https:\/\/solidity-by-example.org\/library\/<\/a><br \/>\n<a href=\"https:\/\/docs.soliditylang.org\/en\/v0.7.6\/using-the-compiler.html\">https:\/\/docs.soliditylang.org\/en\/v0.7.6\/using-the-compiler.html<\/a><\/p>\n<h2>Foundry<\/h2>\n<p>In Foundry tests, Foundry will automatically deploy libraries if they have <code>external<\/code> functions, so you don't need to explicitly link them.<\/p>\n<h2>hardhat-deploy<\/h2>\n<p>Whenever the library is changed, hardhat-deploy will deploy a new implementation and upgrade the proxy:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-typescript\">import { DeployFunction } from \"hardhat-deploy\/dist\/types\"\nimport { QuoteVault } from \"..\/typechain-types\"\n\nconst func: DeployFunction = async function (hre) {\n    const { deployments, ethers } = hre\n\n    \/\/ deploy library\n    await deployments.deploy(\"PerpFacade\", {\n        from: deployerAddress,\n        contract: \"contracts\/lib\/PerpFacade.sol:PerpFacade\",\n    })\n    const perpFacadeDeployment = await deployments.get(\"PerpFacade\")\n\n    \/\/ deploy upgradeable contract\n    await deployments.deploy(\"QuoteVault\", {\n        from: deployerAddress,\n        contract: \"contracts\/QuoteVault.sol:QuoteVault\",\n        proxy: {\n            owner: multisigOwnerAddress, \/\/ ProxyAdmin.owner\n            proxyContract: \"OpenZeppelinTransparentProxy\",\n            viaAdminContract: \"DefaultProxyAdmin\",\n            execute: {\n                init: {\n                    methodName: \"initialize\",\n                    args: [\n                        \"Kantaban USDC-ETH QuoteVault\",\n                        \"kUSDC-ETH\",\n                        usdcDecimals,\n                        USDC,\n                        WETH,\n                    ],\n                },\n            },\n        },\n        libraries: {\n            PerpFacade: perpFacadeDeployment.address,\n        },\n    })\n    const quoteVaultDeployment = await deployments.get(\"QuoteVault\")\n\n    \/\/ must specify library address when instantiating the contract:\n    const quoteVaultFactory = await ethers.getContractFactory(\"contracts\/QuoteVault.sol:QuoteVault\", {\n        libraries: {\n            PerpFacade: perpFacadeDeployment.address,\n        },\n    })\n    const quoteVault = quoteVaultFactory.attach(quoteVaultDeployment.address) as unknown as QuoteVault\n    console.log(await quoteVault.decimals())\n}\n\nexport default func<\/code><\/pre>\n<p>ref:<br \/>\n<a href=\"https:\/\/github.com\/wighawag\/hardhat-deploy#handling-contract-using-libraries\">https:\/\/github.com\/wighawag\/hardhat-deploy#handling-contract-using-libraries<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Whenever the library is changed, hardhat-deploy will deploy a new implementation and upgrade the proxy.<\/p>\n","protected":false},"author":1,"featured_media":853,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[137],"tags":[138,144,11,147,143,140],"class_list":["post-852","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blockchain","tag-ethereum","tag-ethers-js","tag-javascript","tag-smart-contract","tag-solidity","tag-typescript"],"_links":{"self":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/852","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/comments?post=852"}],"version-history":[{"count":0,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/posts\/852\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media\/853"}],"wp:attachment":[{"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/media?parent=852"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/categories?post=852"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vinta.ws\/code\/wp-json\/wp\/v2\/tags?post=852"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}