Ensure the security of your smart contracts

How to Change Bytecode of Already Deployed Smart Contract

Author: MixBytes team
Intro
Developing smart contracts with the Solidity or Vyper programming language always leads to creating some tests in a special environment. Currently in order to deploy newly created smart contracts in testnet several tools exist, the most popular of whcih are hardhat, brownie and truffle. In this paper we will discuss how you can change bytecode of a smart contract already deployed on mainnet and therefore in testnet. This can be useful if you want to change some logic for test purposes or if you want to change prices in oracles, as in a case which will be discussed below.
How to use hardhat functions properly to change bytecode of an already deployed smart contract?
To prepare these tests, we used this article as an example. First of all, you need to install hardhat > 2.4.0 via npm or yarn. Next, you must add a copy of the smart contract code which you would like to change in your project repo. A little tip before we start discussing the code, if you use blockGasLimit in hardhat config, you must tune it right so that tests would execute (in our case we simply removed this parameter from config). Add all necessary changes to this code and deploy it to testnet via ethers.getContractFactory like this:

const oracles = await ethers.getContractFactory("AaveOracle");
const oracle = await oracles.deploy(
      ["0x6B175474E89094C44Da98b954EedeAC495271d0F"], 
      ["0x773616E4d11A78F511299002da57A0a94577F1f4"], 
      "0x5B09E578cfEAa23F1b11127A658855434e4F3e09", 
      WETH.address,
    );
In the code above, we have AaveOracle which contains all code from Aave Oracle with small additions and WETH.address which is simply a string with wrapped ETH in Ethereum mainnet ( 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2). The first parameter in the deploy function is an array of assets which is used in oracle (in our case it is an array of 1 asset == DAI address 0x6B175474E89094C44Da98b954EedeAC495271d0F). The second parameter is an array of data feeds (in our case it is chainlink's data feed for DAI/ETH 0x773616E4d11A78F511299002da57A0a94577F1f4). The third parameter is a fallback oracle (in our case it is simply Aave fallback oracle 0x5B09E578cfEAa23F1b11127A658855434e4F3e09). After all these steps are taken, you can use the hardhat function eth_getCode() to get bytecode of your newly deployed smart contract and after that you must use eth_setCode() to add this code to the contract address in testnet:

const code = await hre.network.provider.send("eth_getCode", [
        oracle.address,
    ]);
await hre.network.provider.send("hardhat_setCode", [
      "0xA50ba011c48153De246E5192C8f9258A2ba79Ca9",
      code,
    ]);
In the code above, we get bytecode of our deployed contract and set it to Aave Oracle which has address 0xA50ba011c48153De246E5192C8f9258A2ba79Ca9.
Conclusion
Hereby you have learned how to change bytecode of already deployed smart contracts for testing purposes in the hardhat framework. More about useful tools for auditors and developers see in our upcoming articles.
Additional readings and tutorials
Other posts