More storage slots for proxy resolution (#4477)
## Problem solved
Add another storage slot for proxy resolution:
keccak256("org.zeppelinos.proxy.implementation")
ref: https://basescan.org/address/0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913#code
<!-- start pr-codex -->
---
## PR-Codex overview
The focus of this PR is to enhance proxy resolution in the `thirdweb` package by adding more storage slots for implementation addresses.
### Detailed summary
- Added more storage slots for proxy resolution in `resolveImplementation.test.ts`
- Updated global setup in `globalSetup` function in `globalSetup.ts`
- Added base chain definitions and RPC URL in `chains.ts`
- Improved implementation address extraction in `resolveImplementation.ts`
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"thirdweb": patch
|
||||
---
|
||||
|
||||
More storage slots for proxy resolution
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
import { ANVIL_CHAIN } from "../../../test/src/chains.js";
|
||||
import { TEST_CLIENT } from "../../../test/src/test-clients.js";
|
||||
import {
|
||||
BASE_USDC_IMPLEMENTATION,
|
||||
BASE_USDC_PROXY_CONTRACT,
|
||||
NFT_DROP_CONTRACT,
|
||||
NFT_DROP_IMPLEMENTATION,
|
||||
POLYGON_USDT_IMPLEMENTATION,
|
||||
@@ -31,6 +33,13 @@ describe("Resolve implementation", async () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("should extract implementation address for base USDC proxy contract", async () => {
|
||||
const resolved = resolveImplementation(BASE_USDC_PROXY_CONTRACT);
|
||||
expect((await resolved).address).to.equal(
|
||||
BASE_USDC_IMPLEMENTATION.toLowerCase(),
|
||||
);
|
||||
});
|
||||
|
||||
it("should extract implementation address for ERC1967 proxy contract", async () => {
|
||||
const implementationAddress = await deployContract({
|
||||
client: TEST_CLIENT,
|
||||
|
||||
@@ -120,24 +120,32 @@ async function getImplementationFromStorageSlot(
|
||||
});
|
||||
|
||||
try {
|
||||
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, {
|
||||
const proxyStoragePromises = [
|
||||
eth_getStorageAt(rpcRequest, {
|
||||
address: contract.address,
|
||||
position:
|
||||
"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc",
|
||||
}),
|
||||
eth_getStorageAt(rpcRequest, {
|
||||
address: contract.address,
|
||||
position:
|
||||
// keccak256("matic.network.proxy.implementation") - used in polygon USDT proxy: https://polygonscan.com/address/0xc2132d05d31c914a87c6611c10748aeb04b58e8f#code
|
||||
"0xbaab7dbf64751104133af04abc7d9979f0fda3b059a322a8333f533d3f32bf7f",
|
||||
});
|
||||
}
|
||||
}),
|
||||
eth_getStorageAt(rpcRequest, {
|
||||
address: contract.address,
|
||||
position:
|
||||
// keccak256("org.zeppelinos.proxy.implementation") - e.g. base USDC proxy: https://basescan.org/address/0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913#code
|
||||
"0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3",
|
||||
}),
|
||||
];
|
||||
|
||||
return `0x${proxyStorage.slice(-40)}`;
|
||||
const proxyStorages = await Promise.all(proxyStoragePromises);
|
||||
const proxyStorage = proxyStorages.find(
|
||||
(storage) => storage !== ZERO_BYTES32,
|
||||
);
|
||||
|
||||
return proxyStorage ? `0x${proxyStorage.slice(-40)}` : AddressZero;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { sha256 } from "@noble/hashes/sha256";
|
||||
import { startProxy } from "@viem/anvil";
|
||||
import { FORK_BLOCK_NUMBER, OPTIMISM_FORK_BLOCK_NUMBER, POLYGON_FORK_BLOCK_NUMBER } from "./src/chains.js";
|
||||
import { FORK_BLOCK_NUMBER, OPTIMISM_FORK_BLOCK_NUMBER, POLYGON_FORK_BLOCK_NUMBER, BASE_FORK_BLOCK_NUMBER } from "./src/chains.js";
|
||||
|
||||
require("dotenv-mono").load();
|
||||
|
||||
@@ -76,11 +76,27 @@ export default async function globalSetup() {
|
||||
},
|
||||
});
|
||||
|
||||
const shutdownBase = await startProxy({
|
||||
port: 8650,
|
||||
options: {
|
||||
chainId: 8453,
|
||||
forkUrl: SECRET_KEY
|
||||
? `https://8453.rpc.thirdweb.com/${clientId}`
|
||||
: "https://mainnet.base.org",
|
||||
forkHeader: SECRET_KEY ? { "x-secret-key": SECRET_KEY } : {},
|
||||
forkChainId: 8453,
|
||||
forkBlockNumber: BASE_FORK_BLOCK_NUMBER,
|
||||
noMining: true,
|
||||
startTimeout: 20000,
|
||||
},
|
||||
});
|
||||
|
||||
return async () => {
|
||||
await shutdownMainnet();
|
||||
await shutdownMainnetWithMining();
|
||||
await shutdownOptimism();
|
||||
await shutdownAnvil();
|
||||
await shutdownPolygon();
|
||||
await shutdownBase();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { anvil } from "../../src/chains/chain-definitions/anvil.js";
|
||||
import { base } from "../../src/chains/chain-definitions/base.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";
|
||||
@@ -11,6 +12,7 @@ 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_BASE_RPC = `http://127.0.0.1:8650/${poolId}`;
|
||||
|
||||
export const FORKED_ETHEREUM_CHAIN = defineChain({
|
||||
...ethereum,
|
||||
@@ -42,6 +44,13 @@ export const ANVIL_CHAIN = defineChain({
|
||||
rpc: ANVIL_RPC,
|
||||
});
|
||||
|
||||
export const FORKED_BASE_CHAIN = defineChain({
|
||||
...base,
|
||||
// override the rpc url
|
||||
rpc: FORKED_BASE_RPC,
|
||||
});
|
||||
|
||||
export const FORK_BLOCK_NUMBER = 19139495n;
|
||||
export const OPTIMISM_FORK_BLOCK_NUMBER = 117525204n;
|
||||
export const POLYGON_FORK_BLOCK_NUMBER = 61430000n;
|
||||
export const BASE_FORK_BLOCK_NUMBER = 19559480n;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getContract } from "../../src/contract/contract.js";
|
||||
import { USDT_ABI } from "./abis/usdt.js";
|
||||
import { FORKED_ETHEREUM_CHAIN, FORKED_POLYGON_CHAIN } from "./chains.js";
|
||||
import { FORKED_ETHEREUM_CHAIN, FORKED_POLYGON_CHAIN, FORKED_BASE_CHAIN } from "./chains.js";
|
||||
import { TEST_CLIENT } from "./test-clients.js";
|
||||
|
||||
// ERC20
|
||||
@@ -13,6 +13,11 @@ export const USDT_CONTRACT_ADDRESS =
|
||||
|
||||
export const POLYGON_USDT_IMPLEMENTATION = "0x7FFB3d637014488b63fb9858E279385685AFc1e2";
|
||||
|
||||
export const BASE_USDC_CONTRACT_ADDRESS =
|
||||
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
||||
|
||||
export const BASE_USDC_IMPLEMENTATION = "0x2ce6311ddae708829bc0784c967b7d77d19fd779";
|
||||
|
||||
export const USDT_CONTRACT = getContract({
|
||||
client: TEST_CLIENT,
|
||||
address: USDT_CONTRACT_ADDRESS,
|
||||
@@ -32,6 +37,12 @@ export const POLYGON_USDT_PROXY_CONTRACT = getContract({
|
||||
chain: FORKED_POLYGON_CHAIN,
|
||||
});
|
||||
|
||||
export const BASE_USDC_PROXY_CONTRACT = getContract({
|
||||
client: TEST_CLIENT,
|
||||
address: BASE_USDC_CONTRACT_ADDRESS,
|
||||
chain: FORKED_BASE_CHAIN,
|
||||
});
|
||||
|
||||
// ERC721
|
||||
|
||||
const DOODLES_ADDRESS = "0x8a90cab2b38dba80c64b7734e58ee1db38b8992e";
|
||||
|
||||
Reference in New Issue
Block a user