✅ 1. 일반 배포 방식

🔹 Solidity (LaunchPad.sol)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract LaunchPad {
uint public value;

constructor(uint _value) {
    value = _value;
}

function setValue(uint _value) external {
    value = _value;
}

}

🔹 배포 스크립트 (TypeScript)

const LaunchPad = await ethers.getContractFactory("LaunchPad");
const contract = await LaunchPad.deploy(42);
await contract.waitForDeployment();

✅ 2. Transparent Proxy Pattern (OpenZeppelin)

🔹 Solidity (LaunchPad.sol)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract LaunchPad is Initializable, OwnableUpgradeable {
uint public value;

function initialize(uint _value) public initializer {
    __Ownable_init();
    value = _value;
}

function setValue(uint _value) external {
    value = _value;
}

}

🔹 배포 스크립트

const LaunchPad = await ethers.getContractFactory("LaunchPad");
const proxy = await upgrades.deployProxy(LaunchPad, [42], {
initializer: "initialize"
});
await proxy.waitForDeployment();

✅ 3. UUPS Proxy Pattern

🔹 Solidity

import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract LaunchPad is Initializable, UUPSUpgradeable, OwnableUpgradeable {
uint public value;

function initialize(uint _value) public initializer {
    __Ownable_init();
    __UUPSUpgradeable_init();
    value = _value;
}

function setValue(uint _value) external {
    value = _value;
}

function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}

}

🔹 배포 스크립트

const LaunchPad = await ethers.getContractFactory("LaunchPad");
const proxy = await upgrades.deployProxy(LaunchPad, [42], {
kind: "uups",
initializer: "initialize"
});
await proxy.waitForDeployment();

✅ 4. Beacon Proxy Pattern

🔹 Solidity (Implementation 계약)

contract LaunchPad {
uint public value;

constructor(uint _value) {
    value = _value;
}

function setValue(uint _value) external {
    value = _value;
}

}

🔹 배포 스크립트

// 1. Implementation 배포
const LaunchPad = await ethers.getContractFactory("LaunchPad");
const implementation = await LaunchPad.deploy(0);

// 2. Beacon 배포
const beacon = await upgrades.deployBeacon(LaunchPad);

// 3. Beacon Proxy 배포
const proxy = await upgrades.deployBeaconProxy(beacon, LaunchPad, [42]);
await proxy.waitForDeployment();

✅ 5. Eternal Storage + Delegatecall (커스텀)

🔹 Storage 계약

contract EternalStorage {
mapping(bytes32 => uint256) internal uintStorage;
}

🔹 Logic 계약

contract LogicContract is EternalStorage {
function setValue(uint _value) public {
uintStorage[keccak256("value")] = _value;
}

function getValue() public view returns (uint) {
    return uintStorage[keccak256("value")];
}

}

🔹 Proxy 계약 (delegatecall)

contract Proxy is EternalStorage {
address public implementation;

constructor(address _impl) {
    implementation = _impl;
}

fallback() external payable {
    address impl = implementation;
    assembly {
        calldatacopy(0, 0, calldatasize())
        let result := delegatecall(gas(), impl, 0, calldatasize(), 0, 0)
        returndatacopy(0, 0, returndatasize())
        switch result
        case 0 { revert(0, returndatasize()) }
        default { return(0, returndatasize()) }
    }
}

}

✅ 6. 다이아몬드 패턴 (EIP-2535)

이건 구조가 복잡해서 요약 형태로만 보여드릴게요.

🔹 구성 요소
• Diamond (main proxy)
• Facet1, Facet2… (기능별 구현 컨트랙트)
• DiamondCutFacet, DiamondLoupeFacet (표준 기능)
• DiamondInit (초기화용)

📌 facet 추가/삭제는 diamondCut()을 통해 관리함

OpenZeppelin에서 직접 지원하지는 않으며, 라이브러리는 Nick Mudge’s EIP-2535 repo 참고.

✨ 마무리 요약

방식 코드 분할 프록시 필요 초기화 방식 배포 복잡도
일반 배포 단일 ❌ constructor ⭐
Transparent Proxy Logic + Proxy ✅ initialize() ⭐⭐
UUPS Logic(Self-upgrade) + Proxy ✅ initialize() ⭐⭐
Beacon Logic + Proxy + Beacon ✅✅ constructor() ⭐⭐⭐
EternalStorage Logic + Proxy + Storage ✅ delegatecall ⭐⭐⭐⭐
다이아몬드 수십 개 facet ✅ DiamondInit ⭐⭐⭐⭐⭐

+ Recent posts