계약 업그레이드

명령행에서 패키지화된 계약을 업그레이드할 수 있습니다.

다음 단계는 샘플 토큰화된 보증금 계약 프로젝트를 업그레이드하는 방법을 보여줍니다. 기타 패키지 계약의 경우 계약 패키지와 함께 번들로 제공되는 README 파일을 참조하십시오.

업그레이드는 기존 프록시 뒤에서 구현을 변경합니다. 즉, 새 프록시를 만들거나 스토리지를 재설정하지 않습니다.

Hardhat 명령줄 인터페이스는 계약 업그레이드를 지원합니다. RPC 프록시 API를 사용하여 스마트 계약을 배포한 경우 변경할 수 없으며 업그레이드할 수 없습니다.

레퍼런스 프로젝트에는 데모 및 테스트를 위한 V2 구현이 포함되어 있습니다.
  • 토큰: contracts/TokenizedDeposit/_testContracts/TokenizedDepositUpgradeableV2.sol
  • 계정: contracts/obp-sdk/accounts/modules/v1/_testContracts/AccountWithERC5982UUPSV2.sol
V2 계약은 V1 저장소 레이아웃을 보존하고, version()를 v2.0.0으로 표시하고, 빈 initializeV2() 재초기화를 포함합니다. 이러한 코드를 참조 코드로 취급하고 검토한 후 실제 업그레이드를 위해 호환되는 고유한 구현으로 바꿉니다.

계약을 업그레이드하려면 계약에 대한 프록시 주소, 구성된 Oracle Blockchain Platform Besu 네트워크 및 거버넌스 제안을 제출할 권한이 필요합니다. 배포된 계약은 활성 상태여야 하며 구성된 업그레이드 승인 경로에 적격해야 합니다.

구현을 수정하기 전에 스토리지 호환성을 유지합니다. 저장 영역 필드만 추가합니다. 기존 필드의 유형을 재정렬, 제거 또는 변경하거나, 상속된 저장소 레이아웃을 변경하거나, 업그레이드 검증을 무시하지 마십시오. 변경 사항이 호환되지 않는 경우 새 프록시를 배포하고 대신 명시적으로 상태를 마이그레이션합니다.

참고:

업그레이드된 소스를 가리켜야 합니다. IMPLEMENTATION_CONTRACT 변수는 Hardhat의 계약 공장으로 전달됩니다. 업그레이드된 버전에 대한 정규화된 Solidity 계약 이름으로 설정합니다.
<path-to-upgraded-contract>.sol:<upgraded-contract-name>
현재 V1 계약에서 변수를 가리키지 마십시오. 예를 들어, 다음 예에는 토큰화된 보증금 V2 참조 구현이 나와 있습니다.
contracts/TokenizedDeposit/_testContracts/TokenizedDepositUpgradeableV2.sol:TokenizedDepositUpgradeableV2
다른 V3 또는 사용자 정의 구현을 만드는 경우 명령의 경로 및 계약 이름을 모두 업그레이드된 소스로 바꿉니다. 변경 후 prepare 명령을 실행하기 전에 컴파일합니다.

토큰 프록시 업그레이드

  1. 다음 명령을 실행하여 토큰 업그레이드를 준비합니다. 준비는 구현 및 스토리지 레이아웃을 검증하고, 정확한 새 구현을 배포하고, 해당 코드 해시 및 라이브러리 주소를 업그레이드 매니페스트에 기록하고, 필요한 거버넌스 의도를 제출합니다. 아직 프록시를 업그레이드하지 않았습니다.
    UPGRADE_ACTION=prepare \
    GOVERNANCE_INTENT_MODE=obp-besu \
    TOKEN_PROXY=<token-proxy-address> \
    IMPLEMENTATION_CONTRACT='contracts/TokenizedDeposit/_testContracts/TokenizedDepositUpgradeableV2.sol:TokenizedDepositUpgradeableV2' \
    LIBRARIES_JSON='{"ERC20TokenHelperLib":null,"ERC20MultiLevelApprovalHelperLib":null}' \
    DEPLOY_LIBRARIES=true \
    INITIALIZER_DATA=0x \
    UPGRADE_MANIFEST=.obp-da/upgrades/deposittoken-v2.json \
    npx hardhat run scripts/upgrade/upgrade-deposittoken.ts --network obp-besu

    DEPLOY_LIBRARIES를 true로 설정하면 널 라이브러리 항목이 배치되고 해당 주소가 검토된 구현 코드 해시의 일부가 됩니다. 라이브러리를 재사용하려면 LIBRARIES_JSON 변수에 기존 호환 라이브러리 주소를 제공하십시오. INITIALIZER_DATA 변수는 upgradeToAndCall 함수에 전달되는 원시 ABI 인코딩 calldata입니다. initializeV2()가 비어 있으므로 제공된 참조 V2 계약에 0x를 사용하십시오. 새 구현을 초기화해야 하는 경우 올바르게 인코딩된 재초기화 calldata를 제공하고 업그레이드 제안의 일부로 검토하십시오.

  2. 거버넌스 제안을 승인합니다. GOVERNANCE_INTENT_MODE 변수가 obp-besu로 설정된 경우 준비 단계는 Oracle Blockchain Platform RPC 프록시를 통해 제안을 제출합니다. 대상 거버넌스 구성에 필요한 승인을 얻습니다. 프록시는 제안이 승인되고 실행 단계가 완료될 때까지 이전 구현에 유지됩니다. 프로젝트가 Oracle Blockchain Platform 엔드포인트 대신 거버넌스 의도를 계약에 직접 제출하도록 구성된 경우에만 GOVERNANCE_INTENT_MODE=json-rpc를 사용합니다.
  3. 토큰 업그레이드를 실행합니다. 승인 후 prepare 명령이 작성한 것과 동일한 매니페스트를 실행합니다.
    UPGRADE_ACTION=execute \
    UPGRADE_MANIFEST=.obp-da/upgrades/deposittoken-v2.json \
    npx hardhat run scripts/upgrade/upgrade-deposittoken.ts --network obp-besu
    스크립트는 upgradeToAndCall 함수를 호출하기 전에 매니페스트 체인 ID, 마감일 및 준비된 구현 바이트 코드 해시를 확인합니다.

계정 프록시 업그레이드

  1. 다음 명령을 실행하여 계정 업그레이드를 준비합니다.
    UPGRADE_ACTION=prepare \
    GOVERNANCE_INTENT_MODE=obp-besu \
    ACCOUNT_PROXY=<account-proxy-address> \
    IMPLEMENTATION_CONTRACT='contracts/obp-sdk/accounts/modules/v1/_testContracts/AccountWithERC5982UUPSV2.sol:AccountWithERC5982UUPSV2' \
    LIBRARIES_JSON='{}' \
    DEPLOY_LIBRARIES=false \
    INITIALIZER_DATA=0x \
    UPGRADE_MANIFEST=.obp-da/upgrades/deposittoken-account-v2.json \
    npx hardhat run scripts/upgrade/upgrade-account.ts --network obp-besu
    
    IMPLEMENTATION_CONTRACT 변수의 전체 값을 새 계정 구현의 경로 및 계약 이름으로 바꿉니다. 계정 업그레이드를 위해 토큰의 소스 경로, 프록시 주소 또는 매니페스트를 재사용하지 마십시오.
  2. 계정 업그레이드 제안이 필요한 거버넌스 승인을 받은 후 다음 명령을 실행하여 계정 업그레이드를 승인하고 완료합니다.
    UPGRADE_ACTION=execute \
    UPGRADE_MANIFEST=.obp-da/upgrades/deposittoken-account-v2.json \
    npx hardhat run scripts/upgrade/upgrade-account.ts --network obp-besu

문제 해결

조건 해결
스토리지 검증 실패 준비 억지로 업그레이드할 수 없습니다. 호환되지 않는 레이아웃 변경 사항을 수정하거나 새 프록시를 배치하고 상태를 마이그레이션합니다.
이전 준비 매니페스트가 만료되었거나 다른 구현을 대상으로 합니다. REPREPARE=true를 설정하고 이전 매니페스트를 감사 레코드로 유지하여 의도적으로 바꾸기를 만듭니다.
실행이 승인 전에 실행됩니다. 먼저 거버넌스 승인을 얻으십시오. 준비된 업그레이드가 실행 가능 상태가 되려면 승인된 의도가 필요합니다.
잘못된 구현이 선택되었습니다. IMPLEMENTATION_CONTRACT 변수가 업그레이드된 소스의 정규화된 path:contract 값을 사용하는지 확인한 다음 새 매니페스트를 재컴파일하고 준비합니다. 다른 구현을 위해 준비된 매니페스트를 실행하지 마십시오.
실행이 재실행되었습니다. 이 스크립트는 이미 업그레이드된 프록시를 감지하고 두 번째 업그레이드 트랜잭션을 전송하는 대신 그 결과를 기록합니다. implementationContract가 없는 이전 매니페스트의 경우 구현 내역을 동기화할 수 있도록 실행할 때 동일한 IMPLEMENTATION_CONTRACT 값을 제공합니다.