Exceeding bytecode size limits and mocking a frontend

Exceeding bytecode size limits and mocking a frontend

Today, I started out working through some updates to my Raider LP Vault contract. After running the main test cases yesterday, I reviewed the less key functions that allow the contract owner to change various variables. Some of these are ERC20 contract addresses, which require approval transactions for the contract to be able to use. By adding these functions, I inadvertently exceeded the bytecode size limit for contracts on Ethereum Mainnet (which applies to other EVM chains like Polygon as well). This took me down quite a rabbit hole.

Reducing Solidity contract bytecode size

EIP-170 limited the size of a deployed contract on Ethereum Mainnet to 24576 bytes.

I did a bit of research while trying to solve this problem and found this article by Mudit Gupta which helped me identify areas to focus on. Additionally, to see the impact of the changes I was making, I installed the hardhat-contract-sizer plugin by Nick Barry.

hardhat-contract-sizer Example

Here are a couple strategies that made the most difference:

Strings are a minimum of 32 bytes, but any usage after that for an error message is a waste. I went through all of my require() statements and shortened the error messages in them to reduce their compiled size.

If statements in contract functions add a lot to the bytecode size because it multiples the execution branches. Sometimes it’s better to just execute a piece of code rather than make it conditional, even if redundant.

For example, If A and B are two tokens, but they could be the same in certain situations, e.g. a reward token and a token in a LP pair. The 1st example creates a larger bytecode than the 2nd example.

Example 1:

A.approve(router, MAX);
if (address(A) !== address(B)) {
    B.approve(router, MAX);
}

Example 2:

A.approve(router, MAX);
B.approve(router, MAX);

Mocking up the frontend for a Web3 app

After resolving the bytecode issues, I started mocking up the web front-end for my contract. There are many similar apps that allow users to deposit tokens to earn yield on them so I reviewed a few of those for inspiration (specifically, Yearn and Pickle, which are both fantastic).

One of the main initial tasks for building a Web3 app is connecting to the user’s wallet and network provider in the browser. A lot of the in-app state depends on a network provider and actions cannot be completed if the user isn’t connected. Therefore, I setup a modal to overlay the app and require the user to connect. It manages a state variable with the connection status to determine when to remove the overlay. Tomorrow, I plan to wire up the Ethereum provider from Metamask into the app and start building the frontend scripts to interact with the contract.

Connect Wallet modal