Resolve implementation from matic proxy implementation slot (#4393)

## Problem solved

keccak256("matic.network.proxy.implementation") - used in polygon USDT proxy: https://polygonscan.com/address/0xc2132d05d31c914a87c6611c10748aeb04b58e8f#code

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on enhancing the Matic (Polygon) proxy contract implementation resolution in the codebase.

### Detailed summary
- Added resolution for Matic proxy contract implementation slot
- Updated test cases for Matic proxy contract implementation
- Added support for Polygon chain in test setup
- Defined Polygon chain constants and RPC URLs
- Updated Ethereum and Polygon chain definitions

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->
This commit is contained in:
kumaryash90
2024-09-04 23:55:47 +00:00
parent f9c351c22d
commit f383fc7484
6 changed files with 67 additions and 3 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---
resolve implementation for matic proxy implementation slot
@@ -10,6 +10,8 @@ import { TEST_CLIENT } from "../../../test/src/test-clients.js";
import {
NFT_DROP_CONTRACT,
NFT_DROP_IMPLEMENTATION,
POLYGON_USDT_IMPLEMENTATION,
POLYGON_USDT_PROXY_CONTRACT,
} from "../../../test/src/test-contracts.js";
import { TEST_ACCOUNT_A } from "../../../test/src/test-wallets.js";
import { getContract } from "../../contract/contract.js";
@@ -22,6 +24,13 @@ describe("Resolve implementation", async () => {
expect((await resolved).address).to.equal(NFT_DROP_IMPLEMENTATION);
});
it("should extract implementation address for matic proxy contract", async () => {
const resolved = resolveImplementation(POLYGON_USDT_PROXY_CONTRACT);
expect((await resolved).address).to.equal(
POLYGON_USDT_IMPLEMENTATION.toLowerCase(),
);
});
it("should extract implementation address for ERC1967 proxy contract", async () => {
const implementationAddress = await deployContract({
client: TEST_CLIENT,
@@ -9,6 +9,8 @@ import { extractMinimalProxyImplementationAddress } from "./extractMnimalProxyIm
// TODO: move to const exports
const AddressZero = "0x0000000000000000000000000000000000000000";
const ZERO_BYTES32 =
"0x0000000000000000000000000000000000000000000000000000000000000000";
/**
* Resolves the implementation address and bytecode for a given proxy contract.
@@ -118,11 +120,23 @@ async function getImplementationFromStorageSlot(
});
try {
const proxyStorage = await eth_getStorageAt(rpcRequest, {
let proxyStorage = "";
proxyStorage = await eth_getStorageAt(rpcRequest, {
address: contract.address,
position:
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
});
if (proxyStorage === ZERO_BYTES32 && contract.chain.id === 137) {
proxyStorage = await eth_getStorageAt(rpcRequest, {
address: contract.address,
position:
// keccak256("matic.network.proxy.implementation") - used in polygon USDT proxy: https://polygonscan.com/address/0xc2132d05d31c914a87c6611c10748aeb04b58e8f#code
"0xbaab7dbf64751104133af04abc7d9979f0fda3b059a322a8333f533d3f32bf7f",
});
}
return `0x${proxyStorage.slice(-40)}`;
} catch {
return undefined;
+17 -1
View File
@@ -1,6 +1,6 @@
import { sha256 } from "@noble/hashes/sha256";
import { startProxy } from "@viem/anvil";
import { FORK_BLOCK_NUMBER, OPTIMISM_FORK_BLOCK_NUMBER } from "./src/chains.js";
import { FORK_BLOCK_NUMBER, OPTIMISM_FORK_BLOCK_NUMBER, POLYGON_FORK_BLOCK_NUMBER } from "./src/chains.js";
require("dotenv-mono").load();
@@ -61,10 +61,26 @@ export default async function globalSetup() {
port: 8648,
});
const shutdownPolygon = await startProxy({
port: 8649,
options: {
chainId: 137,
forkUrl: SECRET_KEY
? `https://137.rpc.thirdweb.com/${clientId}`
: "https://polygon-rpc.com",
forkHeader: SECRET_KEY ? { "x-secret-key": SECRET_KEY } : {},
forkChainId: 137,
forkBlockNumber: POLYGON_FORK_BLOCK_NUMBER,
noMining: true,
startTimeout: 20000,
},
});
return async () => {
await shutdownMainnet();
await shutdownMainnetWithMining();
await shutdownOptimism();
await shutdownAnvil();
await shutdownPolygon();
};
}
+9
View File
@@ -1,5 +1,6 @@
import { anvil } from "../../src/chains/chain-definitions/anvil.js";
import { ethereum } from "../../src/chains/chain-definitions/ethereum.js";
import { polygon } from "../../src/chains/chain-definitions/polygon.js";
import { optimism } from "../../src/chains/chain-definitions/optimism.js";
import { defineChain } from "../../src/chains/utils.js";
@@ -9,6 +10,7 @@ export const FORKED_ETHEREUM_RPC = `http://127.0.0.1:8645/${poolId}`;
export const FORKED_ETHEREUM_WITH_MINING_RPC = `http://127.0.0.1:8646/${poolId}`;
export const FORKED_OPTIMISM_RPC = `http://127.0.0.1:8647/${poolId}`;
export const ANVIL_RPC = `http://127.0.0.1:8648/${poolId}`;
export const FORKED_POLYGON_RPC = `http://127.0.0.1:8649/${poolId}`;
export const FORKED_ETHEREUM_CHAIN = defineChain({
...ethereum,
@@ -16,6 +18,12 @@ export const FORKED_ETHEREUM_CHAIN = defineChain({
rpc: FORKED_ETHEREUM_RPC,
});
export const FORKED_POLYGON_CHAIN = defineChain({
...polygon,
// override the rpc url
rpc: FORKED_POLYGON_RPC,
});
export const FORKED_ETHEREUM_CHAIN_WITH_MINING = defineChain({
...ethereum,
// override the rpc url
@@ -36,3 +44,4 @@ export const ANVIL_CHAIN = defineChain({
export const FORK_BLOCK_NUMBER = 19139495n;
export const OPTIMISM_FORK_BLOCK_NUMBER = 117525204n;
export const POLYGON_FORK_BLOCK_NUMBER = 61430000n;
+12 -1
View File
@@ -1,6 +1,6 @@
import { getContract } from "../../src/contract/contract.js";
import { USDT_ABI } from "./abis/usdt.js";
import { FORKED_ETHEREUM_CHAIN } from "./chains.js";
import { FORKED_ETHEREUM_CHAIN, FORKED_POLYGON_CHAIN } from "./chains.js";
import { TEST_CLIENT } from "./test-clients.js";
// ERC20
@@ -8,6 +8,11 @@ import { TEST_CLIENT } from "./test-clients.js";
export const USDT_CONTRACT_ADDRESS =
"0xdAC17F958D2ee523a2206206994597C13D831ec7";
export const POLYGON_USDT_CONTRACT_ADDRESS =
"0xc2132d05d31c914a87c6611c10748aeb04b58e8f";
export const POLYGON_USDT_IMPLEMENTATION = "0x7FFB3d637014488b63fb9858E279385685AFc1e2";
export const USDT_CONTRACT = getContract({
client: TEST_CLIENT,
address: USDT_CONTRACT_ADDRESS,
@@ -21,6 +26,12 @@ export const USDT_CONTRACT_WITH_ABI = getContract({
abi: USDT_ABI,
});
export const POLYGON_USDT_PROXY_CONTRACT = getContract({
client: TEST_CLIENT,
address: POLYGON_USDT_CONTRACT_ADDRESS,
chain: FORKED_POLYGON_CHAIN,
});
// ERC721
const DOODLES_ADDRESS = "0x8a90cab2b38dba80c64b7734e58ee1db38b8992e";